Lesson 19 of 26 · about 14 min
When things go wrong
Errors are Python's way of saying "I can't do this." try/except lets your program catch an error and recover, and raise lets you signal your own.
🧭 What you need first: Reading and writing files
A trapeze artist practices a dangerous move. Without a net, one slip ends the show. With a net, a slip is just a bounce and a second try.
Your programs run into slips all the time: a user types “twelve” instead of 12, a file is missing, someone divides by zero. Without a net, Python stops with a red error message. try / except is the safety net: “try this risky thing; if this particular kind of slip happens, do this instead.”
Another way: a restaurant order
You order the fish. The kitchen is out of fish. A bad waiter just disappears (crash). A good waiter comes back and says “we’re out of fish, would you like the chicken?” (except). The problem was detected, reported and handled.
Another way: a fire alarm
raise is pulling the fire alarm: “something is wrong, someone needs to deal with it!” The alarm doesn’t fix the fire; it hands the problem to whoever is responsible (the code that called you).
Catch a bad answer
The user types “twelve” first. Step through: watch Python jump from the failed line straight into the except block, then keep going.
Watch the code run, one step at a time
- 1age = None
- 2while age is None:
- 3 try:
- 4 age = int(input("Age? "))
- 5 except ValueError:
- 6 print("Please type a number, like 12")
- 7print("Thanks! Next year you'll be", age + 1)
➜ yellow = the line about to run · ✓ = the line that just ran
The real words
- An exception is an error raised while the program runs. Each kind has a name:
| Exception | Typical cause |
|---|---|
ValueError |
right type, wrong value: int("hello") |
TypeError |
wrong type: "a" + 1 |
ZeroDivisionError |
dividing by zero |
IndexError / KeyError |
list position / dictionary key doesn’t exist |
FileNotFoundError |
opening a file that isn’t there |
- try / except:
try:
result = risky() # if this raises ValueError…
except ValueError:
result = None # …this runs instead of crashing
else:
print("no error!") # runs only if nothing went wrong
finally:
print("always runs") # clean-up, error or not- Catch specific exceptions. A bare
except:catches everything, including bugs you need to know about, and hides them. - When an exception isn’t caught, it travels up the call stack (lesson 10) to the caller, and its caller, until someone catches it or the program stops.
raise ValueError("price can't be negative")signals an error yourself, for example when a function gets an input it can’t handle.assert total >= 0, "total went negative!"stops the program if the condition is False. Asserts are for catching your own mistakes while developing, not for checking user input.
A safe converter
Write safe_int(text) that returns the text converted to an int, or None if it can't be converted. Then write divide(a, b) that raises a ValueError with a friendly message when b is 0, and returns a / b otherwise.
Missing file? No problem
Write load_settings(name) that returns the file's lines as a list (stripped), or an empty list if the file doesn't exist.
📁 Files your program can open: settings.txt
Why is a bare except: (catching everything) usually a bad idea?
Got it?
Finish the lesson to color it in on your map and collect its concept cards.
Did this lesson click?