Exception Handling
Things go wrong. Files don’t exist, users type nonsense, networks drop. try and except let your program handle errors gracefully instead of crashing.
"Every program that talks to the real world will eventually encounter something unexpected. Exception handling is what separates code that crashes from code that recovers."
— ShurAIWhat is an Exception?
An exception is an error that happens while the program is running. Without handling, it crashes the whole program with a traceback message:
print(10 / 0)
# ZeroDivisionError: division by zero
int("hello")
# ValueError: invalid literal for int() with base 10: 'hello'
my_list = [1, 2, 3]
print(my_list[10])
# IndexError: list index out of range
try / except — The Basic Pattern
Wrap risky code in try. If something goes wrong, Python jumps to except instead of crashing:
try:
result = 10 / 0 # this will fail
except ZeroDivisionError:
print("Can't divide by zero!") # runs instead of crashing
print("Program continues...") # this still runs!
Can't divide by zero!
Program continues...
except, continue normally.Catching Multiple Exception Types
Use multiple except blocks to handle different errors differently:
def safe_divide(a, b):
try:
return a / b
except ZeroDivisionError:
print("Error: can't divide by zero")
return None
except TypeError:
print("Error: both values must be numbers")
return None
print(safe_divide(10, 2)) # 5.0
print(safe_divide(10, 0)) # Error: can't divide by zero
print(safe_divide(10, "x")) # Error: both values must be numbers
Getting the Error Message with as
try:
with open("missing.txt") as f:
f.read()
except FileNotFoundError as e:
print(f"Could not open file: {e}")
# Could not open file: [Errno 2] No such file or directory: 'missing.txt'
else and finally
else runs only when no error occurred. finally runs always — error or not. Perfect for cleanup:
def read_file(filename):
try:
f = open(filename)
content = f.read()
except FileNotFoundError:
print(f"File not found: {filename}")
content = None
else:
print("File read successfully!") # only if no error
f.close()
finally:
print("Done attempting to read file.") # always runs
return content
Common Built-in Exceptions
| Exception | When it happens |
|---|---|
| ValueError | Right type, wrong value — int("hello") |
| TypeError | Wrong type — "hi" + 5 |
| ZeroDivisionError | Dividing by zero — 10 / 0 |
| FileNotFoundError | Opening a file that doesn’t exist |
| KeyError | Dict key doesn’t exist — d["missing"] |
| IndexError | List index out of range — lst[99] |
| AttributeError | Object doesn’t have that attribute or method |
Real Example — Safe User Input
def get_age():
"""Ask for age until the user enters a valid number."""
while True:
try:
age = int(input("Enter your age: "))
if age < 0:
print("Age can't be negative. Try again.")
else:
return age
except ValueError:
print("That's not a number. Try again.")
age = get_age()
print(f"You are {age} years old.")
Enter your age: hello
That's not a number. Try again.
Enter your age: -5
Age can't be negative. Try again.
Enter your age: 22
You are 22 years old.
Avoid except Exception or bare except: unless you really mean it. Catching every possible error hides real bugs. Always be as specific as possible — catch the exact exception type you expect.
"try/except doesn’t hide errors — it handles them. There’s a big difference. The goal is always to recover gracefully and keep the program running."
— ShurAI🧠 Quiz — Q1
What happens if code inside a try block raises an exception and there is a matching except block?
🧠 Quiz — Q2
When does the else block run in a try/except/else structure?
🧠 Quiz — Q3
What does except ValueError as e: do?
🧠 Quiz — Q4
When does finally run?