Foundations — Exception handling — try, except (specific), else, finally
Before you can understand try / except / else / finally, you need a small pile of ideas that the parent note quietly assumes. This page builds every one of them from nothing. Read top to bottom — each idea rests on the one above it.
1. A "statement" and running code line by line

Look at the figure. The black arrow is Python's "finger" moving down the list. This top-to-bottom motion is the single most important picture on this page, because the whole point of exception handling is that this finger can suddenly jump.
2. What "goes wrong" actually means — an error/exception
Why an object and not just "the program stops"? Because an object can be passed around and inspected. You can ask "what type of alarm is this?" and react differently to different alarms — exactly what except SomeError does.
Notice each has a descriptive name ending in Error. That name is the "type" — the label the catcher matches against.
3. "Raising" — the finger jumps off the list

In the figure, the finger reaches the red statement that fails. Instead of continuing down (the greyed-out arrow), it leaps sideways (the red arrow) — that leap is a raise. Everything below the failing line in that block is skipped, exactly as parent-note Rule 1 says.
The keyword raise also exists so you can trigger this deliberately — see Raising exceptions — raise and custom exception classes.
4. The call stack — where the finger jumps to

The figure shows three stacked boxes: main called A, which called B. The red arrow shows what happens when B raises without catching: the alarm travels back up the stack — first offered to B, then A, then main. This upward travel is what the parent note means by propagate up the call stack.
5. isinstance and the "is-a" relationship
The parent note's matching rule is isinstance(E, ClauseType). You must understand this or Example 3 (order of excepts) is magic.

The figure shows the little family tree the parent note uses: Exception at the top, LookupError under it, and KeyError under that. The red highlight traces the chain for a KeyError: it is-a KeyError, is-a LookupError, is-a Exception. So except LookupError: catches a KeyError, because isinstance(KeyError_object, LookupError) is True.
6. Blocks and indentation — how Python groups lines
try:
a() # these two lines are the
b() # BODY of the try block
except ValueError:
c() # body of the except blockWhy this matters: "the rest of the try block is skipped" means the still-indented lines under try. Indentation is literally how Python knows where the risky region ends and the handler begins. There are no {} braces — the spaces are the structure.
7. Cleanup and why finally exists
How these foundations feed the topic
Equipment checklist
Self-test: cover the right side and answer each. If any stumps you, re-read that section.
What does Python's "finger" normally do with a list of statements?
What is an exception, concretely?
ValueError) and a message, created when a statement can't be completed.When a line raises, what happens to the lines below it in the same block?
Where does a raised exception travel if nobody catches it locally?
Does except LookupError: catch a KeyError? Why?
KeyError is a subclass of LookupError, so isinstance(theKeyError, LookupError) is True.Why must specific (child) excepts come before general (parent) ones?
How does Python know where the try body ends and the except begins?
Why does finally need to exist at all?
finally is the one place guaranteed to run so resources still get returned.Connections
- Parent: Exception handling (topic)
- Raising exceptions — raise and custom exception classes
- The exception class hierarchy — BaseException, Exception, LookupError
- Context managers — with statement and __enter__/__exit__
- File handling in Python
- Debugging and tracebacks
- Logging vs printing errors