Beyond a bare try/except
Error handling is where production code differs most from tutorial code: user input is malformed, files go missing, networks drop mid-request. The difference between a service that reports a clear error and one that silently corrupts data usually comes down to a few well-placed except clauses.
You met try/except in Python for Beginners and used it in lessons 4-1 and 5-2. Now the full toolkit:
try: data = json.loads(text) except json.JSONDecodeError as e: print("bad input:", e) else: print("parsed", len(data), "keys") finally: print("attempt finished")
- Catch specific exceptions. A bare
except:swallows typos likeNameErrorand hides real bugs. as ebinds the exception object so you can log its message.elseruns only when no exception happened, keeping the happy path out of the risky block.finallyalways runs, for cleanup.
And raise ValueError("amount must be positive") throws your own error when a caller hands you nonsense. Failing loudly beats corrupting data silently.
Code exercise · python
Run this program. The same function handles good input, bad JSON, and always reports the attempt via finally.
Custom exceptions
Big programs define their own exception types so callers can react precisely. It is lesson 3-4 inheritance, usually with an empty body:
class InsufficientFunds(Exception): pass def withdraw(balance, amount): if amount > balance: raise InsufficientFunds(f"need {amount}, have {balance}") return balance - amount
Now except InsufficientFunds: catches exactly this business error while a TypeError from a genuine bug still crashes visibly, which is what you want. Convention: name them like errors, inherit from Exception (never from BaseException), and put them near the code that raises them.
Code exercise · python
Your turn. Define an EmptyCartError, make checkout raise it when the cart is empty, and catch it in the loop so the output matches.
Quiz
Why is a bare except: considered harmful?
Quiz
In try/except/else, when does the else block run?