1.3.5 · D1Python Intermediate

Foundations — Exception handling — try, except (specific), else, finally

1,633 words7 min readBack to topic

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

Figure — Exception handling — try, except (specific), else, finally

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

Figure — Exception handling — try, except (specific), else, finally

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

Figure — Exception handling — try, except (specific), else, finally

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.

Figure — Exception handling — try, except (specific), else, finally

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 block

Why 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

Statements run top to bottom

Raising abandons the line

Exception is an alarm object

Call stack: jump travels up

isinstance: subclass is-a parent

Blocks via indentation

Resources must be returned

try / except / else / finally


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?
Runs them one at a time, top to bottom.
What is an exception, concretely?
A small object with a type (like 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?
They are skipped — the whole statement is abandoned, and nothing it would have assigned gets assigned.
Where does a raised exception travel if nobody catches it locally?
Up the call stack, offered to each caller in turn, until caught — or it reaches the top and crashes with a traceback.
Does except LookupError: catch a KeyError? Why?
Yes, because KeyError is a subclass of LookupError, so isinstance(theKeyError, LookupError) is True.
Why must specific (child) excepts come before general (parent) ones?
A parent clause catches all its children first, making a later child clause unreachable.
How does Python know where the try body ends and the except begins?
By indentation — the equally-indented lines form each block; there are no braces.
Why does finally need to exist at all?
Because a raise can skip your cleanup line; 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