Errors and Exceptions
What Are Errors?
Errors (also called exceptions) are problems that occur when your program runs. When Python encounters an error, it stops running and displays an error message.
Example:
age = int(input("Enter your age: "))
# If user types "twenty" instead of "20", Python crashes with an error!
Output:
Enter your age: twenty
ValueError: invalid literal for int() with base 10: 'twenty'
Without error handling, your program crashes and stops. With error handling, you can catch these errors and keep your program running.
← Back to where you were | → Start the course from the beginning
Common Types of Errors
ValueError
Happens when you try to convert something to the wrong type.
age = int("twenty") # ValueError: can't convert "twenty" to integer
number = float("abc") # ValueError: can't convert "abc" to float
TypeError
Happens when you use the wrong type of data for an operation.
result = "5" + 5 # TypeError: can't add string and integer
name = "Alice"
name[0] = "B" # TypeError: strings are immutable
KeyError
Happens when you try to access a dictionary key that doesn’t exist.
flashcards = {"Dog": "Hund", "Cat": "Katze"}
translation = flashcards["Bird"] # KeyError: 'Bird' doesn't exist
IndexError
Happens when you try to access a list index that doesn’t exist.
scores = [85, 92, 78]
score = scores[5] # IndexError: list only has 3 items (indices 0-2)
FileNotFoundError
Happens when you try to open a file that doesn’t exist.
with open("missing_file.txt", "r") as file:
content = file.read() # FileNotFoundError: file doesn't exist
ZeroDivisionError
Happens when you try to divide by zero.
result = 10 / 0 # ZeroDivisionError: division by zero
← Back to where you were | → Start the course from the beginning
The try/except Pattern
The try/except pattern lets you catch errors and handle them gracefully instead of crashing.
Basic Syntax
try:
# Code that might cause an error
risky_code()
except:
# What to do if ANY error occurs
print("Something went wrong!")
How it works:
- Python tries to run the code in the
tryblock - If an error occurs, it jumps to the
exceptblock - If no error occurs, the
exceptblock is skipped
Simple Example
# Without error handling - crashes!
age = int(input("Enter your age: "))
print(f"You are {age} years old")
# With error handling - doesn't crash!
try:
age = int(input("Enter your age: "))
print(f"You are {age} years old")
except:
print("That's not a valid age!")
What happens:
Enter your age: twenty
That's not a valid age!
# Program continues running!
← Back to where you were | → Start the course from the beginning
Catching Specific Errors
It’s better to catch specific error types so you know exactly what went wrong.
Single Exception Type
try:
age = int(input("Enter your age: "))
print(f"You are {age} years old")
except ValueError:
print("Please enter a number, not text!")
Multiple Exception Types
try:
flashcards = {"Dog": "Hund", "Cat": "Katze"}
word = input("Enter a word: ")
translation = flashcards[word]
print(f"{word} = {translation}")
except KeyError:
print("That word isn't in the flashcards!")
except ValueError:
print("Invalid input format!")
Catching Multiple Errors with One Block
try:
result = 10 / int(input("Enter a number: "))
print(result)
except (ValueError, ZeroDivisionError):
print("Invalid input or division by zero!")
← Back to where you were | → Start the course from the beginning
The Else and Finally Clauses
Else - Runs if NO Error Occurs
try:
age = int(input("Enter your age: "))
except ValueError:
print("Invalid age!")
else:
# Only runs if no error occurred
print(f"You are {age} years old")
Finally - Always Runs (Error or Not)
try:
file = open("data.txt", "r")
content = file.read()
except FileNotFoundError:
print("File not found!")
finally:
# Always runs, even if there was an error
print("Closing file operations")
file.close()
Note: When using with statements, you don’t need finally for files because they close automatically.
Complete Pattern
try:
# Try to do something risky
result = risky_operation()
except SpecificError:
# Handle specific error
print("Specific error occurred")
else:
# Only if no error
print("Success!")
finally:
# Always runs
print("Cleanup complete")
← Back to where you were | → Start the course from the beginning
Practical Examples
Example 1: Safe Number Input
def get_number(prompt):
"""Keep asking until user enters a valid number."""
while True:
try:
number = int(input(prompt))
return number # Success - return the number
except ValueError:
print("That's not a number! Try again.")
# Use it:
age = get_number("Enter your age: ")
print(f"You are {age} years old")
What happens:
Enter your age: twenty
That's not a number! Try again.
Enter your age: 25
You are 25 years old
Example 2: Safe Dictionary Access
flashcards = {"Dog": "Hund", "Cat": "Katze", "House": "Haus"}
word = input("Enter English word: ")
try:
translation = flashcards[word]
print(f"{word} = {translation}")
except KeyError:
print(f"Sorry, '{word}' is not in the flashcards")
print("Would you like to add it?")
Example 3: Safe File Loading
import json
def load_flashcards(filename):
"""Load flashcards from file, or return empty dict if file doesn't exist."""
try:
with open(filename, "r") as file:
flashcards = json.load(file)
print(f"✓ Loaded {len(flashcards)} flashcards")
return flashcards
except FileNotFoundError:
print("No flashcard file found. Starting fresh!")
return {}
except json.JSONDecodeError:
print("Flashcard file is corrupted. Starting fresh!")
return {}
# Use it:
flashcards = load_flashcards("flashcards.json")
Example 4: Division Calculator
def safe_divide(a, b):
"""Divide two numbers safely."""
try:
result = a / b
return result
except ZeroDivisionError:
print("Error: Cannot divide by zero!")
return None
except TypeError:
print("Error: Both inputs must be numbers!")
return None
# Use it:
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # Error message, returns None
print(safe_divide("10", 2)) # Error message, returns None
Example 5: Flashcard Practice with Error Handling
import json
import random
def load_flashcards():
"""Load flashcards with error handling."""
try:
with open("flashcards.json", "r") as file:
flashcards = json.load(file)
if not flashcards:
print("Flashcard file is empty!")
return {}
return flashcards
except FileNotFoundError:
print("No flashcards found. Please add some first!")
return {}
except json.JSONDecodeError:
print("Flashcard file is corrupted!")
return {}
def practice_flashcards():
"""Practice flashcards with error handling."""
flashcards_list = load_flashcards()
if not flashcards:
print("No flashcards to practice!")
return
# Practice loop
random.shuffle(flashcard_list)
score = 0
for english, german in flashcard_list:
print(f"\nTranslate: {english}")
user_answer = input("Your answer: ").strip()
if user_answer.lower() == german.lower():
print("✓ Correct!")
score += 1
else:
print(f"✗ Wrong! The answer was: {german}")
# Display results
total = len(flashcard_list)
percentage = (score / total) * 100
print(f"\n--- Results ---")
print(f"Score: {score}/{total} ({percentage:.1f}%)")
# Run the practice
practice_flashcards()
← Back to where you were | → Start the course from the beginning
—
Best Practices
✅ DO: Catch Specific Errors
# Good - clear what error you're handling
try:
age = int(input("Age: "))
except ValueError:
print("Please enter a number")
❌ DON’T: Catch All Errors Blindly
# Bad - hides what went wrong
try:
age = int(input("Age: "))
except:
print("Something went wrong") # What went wrong?
✅ DO: Provide Helpful Error Messages
# Good - user knows what to do
except ValueError:
print("Please enter a valid number (digits only)")
❌ DON’T: Use Silent Failures
# Bad - error is hidden, user confused
try:
age = int(input("Age: "))
except:
pass # Error is completely hidden!
✅ DO: Keep Try Blocks Small
# Good - only risky code in try block
user_input = input("Enter age: ")
try:
age = int(user_input)
except ValueError:
print("Invalid age")
else:
print(f"You are {age}")
❌ DON’T: Put Too Much in Try Blocks
# Bad - hard to know what caused the error
try:
user_input = input("Enter age: ")
age = int(user_input)
print(f"You are {age}")
next_age = age + 1
print(f"Next year: {next_age}")
except:
print("Something went wrong") # What exactly?
When to Use Error Handling
Use try/except when:
- ✅ Converting user input to numbers
- ✅ Opening/reading files
- ✅ Accessing dictionary keys
- ✅ Working with external data (JSON, CSV)
- ✅ Performing calculations that might fail
- ✅ Any operation that could fail for reasons outside your control
Don’t use try/except for:
- ❌ Logic errors in your code (fix the bug instead!)
- ❌ Checking if a variable exists (use
ifstatements) - ❌ Hiding programming mistakes
← Back to where you were | → Start the course from the beginning
—
Common Patterns
Pattern 1: Input Validation Loop
while True:
try:
num = int(input("Enter a number: "))
break # Success - exit loop
except ValueError:
print("Invalid! Try again.")
Pattern 2: Safe Dictionary Get
# Option 1: try/except
try:
value = my_dict[key]
except KeyError:
value = default_value
# Option 2: .get() method (simpler!)
value = my_dict.get(key, default_value)
Pattern 3: File Loading with Fallback
try:
with open("data.json", "r") as file:
data = json.load(file)
except (FileNotFoundError, json.JSONDecodeError):
data = {} # Use empty dict as fallback
Pattern 4: Multiple Attempts
max_attempts = 3
attempts = 0
while attempts < max_attempts:
try:
age = int(input("Enter age: "))
break
except ValueError:
attempts += 1
print(f"Invalid! {max_attempts - attempts} attempts left")
if attempts == max_attempts:
print("Too many failed attempts!")
Debugging Tip: Print Error Details
Sometimes you want to see the actual error message:
try:
result = risky_operation()
except Exception as e:
print(f"Error occurred: {e}")
print(f"Error type: {type(e).__name__}")
Example:
try:
age = int("twenty")
except Exception as e:
print(f"Error: {e}")
# Output: Error: invalid literal for int() with base 10: 'twenty'
print(f"Type: {type(e).__name__}")
# Output: Type: ValueError
← Back to where you were | → Start the course from the beginning
—
Summary
Key takeaways:
- Errors crash programs - use try/except to prevent this
- Try/except pattern:
try: # Risky code except SpecificError: # Handle error - Catch specific errors - not all errors blindly
- Provide helpful messages - tell users what went wrong
- Keep try blocks small - easier to debug
- Common use cases - user input, files, dictionary access
Most common errors for beginners:
ValueError- Invalid conversionsKeyError- Missing dictionary keysIndexError- Invalid list indicesFileNotFoundError- Missing filesTypeError- Wrong data types
← Back to where you were | → Start the course from the beginning
