Python's except quirk
Alex Becker
Posted on March 11, 2019
Let me show you my favorite Python quirk. What would you expect this python code to do?
e = 2.718
try:
1/0
except ZeroDivisionError as e:
pass
print(e)
If you come to Python from another programming language, you might expect that the except
clause introduces a nested scope, so assigning to e
in the clause does not effect the pre-existing e
variable in the outer scope. However, in python control structures do not generally introduce nested scoped (comprehensions being the exception), so with more python experience you would probably expect this to print a ZeroDivisionError
instance.
Actually, in the standard CPython implementation it prints nothing; instead, the last line raises a NameError
. Is this a bug? Actually, it was quite intentional. If you look at the bytecode generated by the except clause, you see:
LOAD_CONST 0 (None)
STORE_NAME 1 (e)
DELETE_NAME 1
When control flow exits the except
block, python deletes the name from scope. Why? Because the exception holds a reference to the current stack frame, which contains everything in scope. Since python is manages memory primary via reference count, this means that nothing in the current scope will be freed until the next round of garbage collection runs, if at all. The current behavior is a compromise between memory usage, ease of implementation, and cleanliness of the language. It is a bit of a wart, but I think it embodies a one of the things I love about Python: not letting purity get in the way of practicality.
But that only explains the DELETE_NAME
instruction. Why does CPython set e
to None
if it's going to delete it immediately afterwards? Well, imagine you had the same thought as the CPython team, and decided to clean up the exception reference at the end of your except
block:
try:
1/0
except ZeroDivisionError as e:
...
del e
At the end of your except
block, CPython will try to delete the name e
—which you already deleted! To get around this, CPython assigns e = None
before deleting e
to guarantee that e
exists.
Posted on March 11, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.