| layout | default |
|---|---|
| title | Exception Handling |
| parent | Lessons |
| nav_order | 12 |
| permalink | /lessons/exception-handling/ |
| course_lesson | true |
| course_index | 12 |
| previous_page | /lessons/file-handling/ |
| previous_title | File Handling |
| next_page | /lessons/modules-and-packages/ |
| next_title | Modules and Packages |
An exception is a runtime event that stops normal execution unless the program handles it.
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
- 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") # FileNotFoundErrortry:
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.
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 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.
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 ageRaising an exception is not the same as handling it. The caller can decide how to present the problem.
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.
- 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.
try:
age = int("ten")
except ZeroDivisionError:
print("Please enter a whole number")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:
passShow 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.
Try these problems on this page. For each one, name the operation that can fail and the friendly message the user should see.
- 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.
Make the expense tracker reject invalid amounts, negative values, missing descriptions, and unavailable files with helpful messages.
Make a calculator that continues running after invalid input and handles division by zero. Explain which exception each handler catches.