You think errors stop your program. In Python, they are part of control flow.
Today, you understand how Python handles errors under the hood.
Today’s Goal
By the end of today, you will:
- Understand how exceptions work internally
- Learn stack unwinding
- Use exceptions correctly (and not overuse them)
- Understand performance implications
The Illusion
x = int("abc")
You think:
Program crashes
Reality:
Python raises an exception object and unwinds the stack
What Is an Exception?
An exception is:
- an object
- representing an error condition
Basic Example
try:
x = int("abc")
except ValueError:
print("invalid input")
What Happens Internally
- Error occurs
- Exception object created
- Current frame interrupted
- Stack unwinds
- Matching
exceptblock executed
Stack Unwinding
[ function3 ]
[ function2 ]
[ function1 ]
[ main ]
Exception moves up until handled.
Key Insight
Exceptions are propagated up the call stack.
Multiple Except Blocks
try:
x = int("abc")
except ValueError:
print("value error")
except Exception:
print("general error")
Order Matters
Specific exceptions should come before general ones.
Finally Block
try:
f = open("file.txt")
finally:
print("cleanup")
Always executes.
Else Block
try:
x = int("10")
except:
pass
else:
print("success")
Runs only if no exception occurs.
Raising Exceptions
raise ValueError("invalid value")
Custom Exceptions
class MyError(Exception):
pass
Exception Cost
Exceptions are expensive.
Because:
- object creation
- stack unwinding
- frame cleanup
Performance Insight
Do NOT use exceptions for normal control flow.
Bad:
try:
x = d["key"]
except KeyError:
x = None
Better:
x = d.get("key")
Exception Chaining
try:
raise ValueError()
except ValueError as e:
raise RuntimeError() from e
Preserves original error.
Tracebacks (Debugging Insight)
When an exception is not handled, Python prints a traceback:
Traceback (most recent call last):
File "main.py", line 2, in <module>
x = int("abc")
ValueError: invalid literal for int()
What It Shows
- call stack (from bottom to top)
- exact line where error occurred
- exception type and message
Using traceback Module
import traceback
try:
int("abc")
except:
traceback.print_exc()
Insight
Traceback is your window into stack state during failure.
Why This Matters
Exceptions affect:
- control flow
- debugging
- performance
Real Example
def divide(a, b):
if b == 0:
raise ValueError("division by zero")
return a / b
Your Task
- create custom exception
- observe stack trace
- compare try/except vs condition checks
Common Mistakes
- catching broad Exception
- swallowing errors silently
- using exceptions as logic
Think Deeper
- What happens to stack during exception?
- Why are exceptions expensive?
- When should you raise vs return?
Subtle Insight (CRITICAL)
Exceptions are structured control flow, not just errors.
Tomorrow
Iterators & Generators — lazy execution and memory efficiency
Rule
- Handle specific exceptions
- Avoid silent failures
- Use exceptions wisely
See you in Day 8.