The Exception Tree
ZeroDivisionError is not just a message. It is a name — and every one of those names sits somewhere in a family tree with BaseException at the top. This is not trivia. The tree is exactly what decides which except block catches which error.
1The tree, with the parts you will actually meet
Python has around sixty built-in exceptions. Here are the ones worth knowing, in their proper places. Indentation shows descent — each one is a kind of the thing above it:
SystemExit and KeyboardInterrupt hang off BaseException rather than Exception, and that placement is deliberate: they are not really errors, they are requests to stop. Keeping them out from under Exception means an ordinary handler cannot accidentally swallow your Ctrl+C.2Why a family tree matters at all
Because catching a parent catches all its children. That single rule is the whole reason the shape of the tree is worth knowing:
try:
x = 10 / 0
except ArithmeticError:
print('caught — ZeroDivisionError is a kind of ArithmeticError')caught — ZeroDivisionError is a kind of ArithmeticError
The error raised was a ZeroDivisionError. The handler names ArithmeticError, which is its parent, and it caught it anyway. Walk further up and the same thing keeps working — except Exception would have caught it too, and so would except BaseException.
ZeroDivisionError → ArithmeticError → Exception → BaseExceptionAny of those four names in an except will catch it. The further up you go, the more other things you catch along with it — which is the subject of the “Catching the Right One” lesson, and the reason the first name is almost always the right choice.
3Exception: the root of everything you care about
Nearly every exception a program of yours can raise is somewhere under Exception. That makes it the widest net worth having, and the reason you will sometimes see except Exception written as a last resort at the very outside of a large program.
It is also the reason except Exception is such a bad habit anywhere else. It catches the error you were expecting and every error you were not, and reports them all the same way. There is a whole lesson on that two pages from here.
4Why SyntaxError is in the tree and still uncatchable
SyntaxError sits under Exception like the others, which looks as though you ought to be able to catch it. In your own file, you cannot — and the last lesson explained why. Python reads the whole file before running any of it, so a syntax error in this file is raised before your try exists.
SyntaxError is a proper exception class — it is just that the mistake happens too early in the life of your program for any handler in that program to be running yet.5The names worth memorising
| Exception | Raised when | Example |
|---|---|---|
ZeroDivisionError | you divide by zero | 10 / 0 |
ValueError | the type is right, the value is not | int('twelve') |
TypeError | the type itself is wrong | '2' + 2 |
IndexError | the position does not exist | marks[5] on 3 items |
KeyError | the key does not exist | record['Sara'] |
NameError | the name was never created | print(totl) |
FileNotFoundError | the file is not there | opening a missing file |
You do not have to learn the whole tree. You have to learn these seven names and the one rule that a parent catches its children — that is everything the chapter needs from you.
6Recap
Every exception in Python descends from it. Nothing sits outside the tree.
SystemExit, KeyboardInterrupt and GeneratorExit deliberately sit beside it, not under it — they are requests to stop, not errors.
except ArithmeticError catches ZeroDivisionError. This one rule is why the shape of the tree matters.
ZeroDivisionError → ArithmeticError → Exception → BaseException. Each step widens the net, usually further than you meant.
SyntaxError is a real exception class, but a syntax error in your file happens before your try block exists.
- 1
Catch a
ZeroDivisionErrorusingexcept ArithmeticErrorand check that it works.Hint · A parent catches its children. That is the whole rule.
- 2
Do the same with
except Exception, then withexcept IndexError.Hint · The first catches it; the second does not, because
IndexErroris on a different branch. - 3
Write down the chain from
KeyErrorup toBaseException.Hint ·
KeyError → LookupError → Exception → BaseException. Four names, same shape as the division one.
Which of these catches a ZeroDivisionError?
Why do SystemExit and KeyboardInterrupt sit under BaseException rather than Exception?
SyntaxError is in the tree. Can you catch one in your own file?