Error Handling
Errors Are Inevitable
Every program that interacts with the outside world will eventually encounter something unexpected. A user types text where a number was expected. A file doesn't exist. A network connection drops. A list is empty when it shouldn't be.
You have two choices: let the program crash with a traceback, or handle the problem and respond sensibly.
Professional programs do the second. This lesson gives you the tools.
The try / except Block
Type a word instead of a number. The program catches the error and responds calmly — no traceback, no crash.
Here's what happened:
- Python attempts the code inside
try - If an exception occurs, Python immediately jumps to the matching
exceptblock - If no exception occurs, the
exceptblock is skipped entirely
ValueError is the specific exception type we're catching — the error Python raises when a conversion like int("hello") fails. Being specific matters: catching only the exception you expect means other unexpected errors still surface loudly.
Catching Specific Exceptions
Different problems raise different exception types. You can handle each separately:
Each except clause handles one specific problem. Python checks them in order and runs the first one that matches.
The else Clause
try/except supports an optional else block — code that runs only when no exception occurred:
The else block only runs when try completed without errors. This is cleaner than putting all the success logic inside the try block — it keeps the "normal path" separate from the "error path".
The finally Clause
finally runs no matter what — whether an exception occurred or not, whether it was caught or not. It always executes.
finally is the right place for cleanup code — releasing resources, closing connections, printing a completion message — anything that must happen regardless of outcome.
Accessing the Exception Object
You can capture the exception itself to inspect its message:
The as e gives you a reference to the exception object. str(e) or just e in an f-string gives you the message Python would have printed in the traceback.
Raising Your Own Exceptions
You can raise exceptions yourself using raise. This lets you signal error conditions in your own code with precise, meaningful messages:
raise ValueError("message") creates and raises an exception immediately. The calling code can catch it just like any built-in exception.
This is how you write functions that communicate failure clearly — not by returning None or -1 and hoping the caller notices, but by raising an exception with a descriptive message that makes the problem impossible to miss.
Building a Robust Input Function
A common pattern: keep asking until valid input is received.
The loop keeps running until return is reached — which only happens on valid input. Any ValueError (from either float() or the manual raise) sends the user back to the prompt. This is a real-world pattern used in almost every interactive program.
Common Exception Types
A reference you'll use often:
| Exception | When it occurs |
|---|---|
ValueError | Right type, wrong value (int("hello")) |
TypeError | Wrong type entirely ("a" + 1) |
IndexError | List index out of range |
KeyError | Dictionary key not found |
ZeroDivisionError | Division by zero |
AttributeError | Attribute or method doesn't exist |
FileNotFoundError | File doesn't exist |
NameError | Variable not defined |
What You Have Learned
Error handling is what separates scripts from programs.
The key ideas:
try / exceptcatches exceptions and lets you respond instead of crashing- Always catch specific exception types — never catch everything blindly
elseruns when no exception occurred — keeps success logic separatefinallyalways runs — use it for cleanupas ecaptures the exception object and its messageraise ExceptionType("message")signals error conditions from your own code- Wrap repeated user input in a
while Trueloop withtry/exceptfor robust input collection
In the next lesson, you'll learn how to read and write files — persisting data beyond the life of a single program run.