12 - Exception Handling
An exception is a runtime event that stops normal execution unless the program handles it.
A simple picture
An exception is like an emergency card passed from one helper to another. Normal work pauses. A helper that knows this exact problem may handle it and continue safely; otherwise the card keeps moving outward.
risky operation -> exception -> matching except block -> recovery
Types of problems
- A syntax error means Python cannot understand the program.
- A runtime exception occurs while understandable code is running.
- A logic error runs successfully but produces the wrong result.
Examples of runtime exceptions:
int("ten") # ValueError
10 / 0 # ZeroDivisionError
open("missing") # FileNotFoundError
Basic try and except
try:
age = int(input("Age: "))
except ValueError:
print("Please enter a whole number.")
else:
print(f"Age recorded: {age}")
Put only the risky operation in the try block. Catch the specific exception you expect.
Important fact:
trydoes not mean “ignore every problem.” It marks an operation that may fail in an expected way. Catch only exceptions you understand and can handle correctly.
Multiple exceptions
try:
numerator = float(input("Numerator: "))
denominator = float(input("Denominator: "))
print(numerator / denominator)
except ValueError:
print("Use numeric values.")
except ZeroDivisionError:
print("The denominator cannot be zero.")
Different errors deserve different recovery messages.
else and finally
else runs only when no exception occurred. finally runs whether the operation succeeded or failed:
file = None
try:
file = open("notes.txt", encoding="utf-8")
print(file.read())
except FileNotFoundError:
print("Notes file does not exist.")
finally:
if file is not None:
file.close()
For files, prefer with open(...); it handles cleanup automatically.
Raising an exception
Use raise when a function receives data that violates its contract:
def set_age(age):
if age < 0:
raise ValueError("age cannot be negative")
return age
Raising an exception is not the same as handling it. The caller can decide how to present the problem.
Validation loop
while True:
try:
number = int(input("Enter a number: "))
break
except ValueError:
print("That was not a whole number. Try again.")
The loop repeats only for the expected invalid-input case.
Common mistakes
- Catching every error with bare
except. - Putting the entire program inside one huge
tryblock. - Showing a technical traceback to a beginner user when recovery is possible.
- Silently ignoring an exception with
pass. - Using exceptions to hide a logic error.
Bug Hunter
Bug 1 — wrong exception type
try:
age = int("ten")
except ZeroDivisionError:
print("Please enter a whole number")
Bug 2 — risky operation outside try
number = int(input("Number: "))
try:
print(number)
except ValueError:
print("Please enter a whole number")
Bug 3 — error silently hidden
try:
total = 100 / 0
except Exception:
pass
Show Bug Hunter fixes
# Bugs 1 and 2
try:
age = int(input("Age: "))
except ValueError:
print("Please enter a whole number")
# Bug 3
try:
total = 100 / 0
except ZeroDivisionError:
print("The denominator cannot be zero")
Optional deeper look: how does an exception find a handler?
When an exception is raised, Python stops the current normal path and looks for a matching handler. If the current function has none, Python finishes that call frame and checks its caller. This process is called stack unwinding. finally blocks and context-manager cleanup still run during unwinding.
Practice
Try these problems on this page. For each one, name the operation that can fail and the friendly message the user should see.
Problems
- Safely convert user input into an integer.
- Handle division by zero.
- Handle a missing file.
- Reject a negative age with
raise. - Keep asking until the user enters a valid number.
- Predict which exception each short program raises.
- Make a calculator continue after invalid operations.
- Validate a menu choice and report a useful message.
- Use
elseandfinallycorrectly in a file-reading program. - Build a robust command-line expense entry program.
Show hints
- Catch
ValueErroraroundint(). - Catch
ZeroDivisionErroror check the divisor first. - Catch
FileNotFoundError. - Check the value and raise
ValueErrorwith a clear message. - Put input inside a loop and leave only after success.
- Read the failing operation and match it to an exception type.
- Catch expected errors inside the loop.
- Check membership in the allowed choices.
elseis for success;finallyruns every time.- Validate each field before saving it.
Show solution ideas
- Put
int(text)insidetryand handleValueError. - Handle
ZeroDivisionErrorwith a message about the denominator. - Catch the missing path and offer a recovery message.
if age < 0: raise ValueError("age cannot be negative").- Use
while True,breakafter successful conversion, and a specific handler. - Bad numeric text is
ValueError; zero division isZeroDivisionError; a missing path isFileNotFoundError. - Keep the loop outside the individual operation attempt.
- Use
if choice not in allowed. - Put success-only code in
elseand cleanup infinally. - Catch expected errors at the user-interface boundary and keep the program running.
Homework
Make the expense tracker reject invalid amounts, negative values, missing descriptions, and unavailable files with helpful messages.
Checkpoint
Make a calculator that continues running after invalid input and handles division by zero. Explain which exception each handler catches.