Given the following code:
msg = "test"
try:
"a"[1]
except IndexError as msg:
print("Error happened")
print(msg)
Can somebody explain why this causes the following output in Python 3?
Error happened
Traceback (most recent call last):
File "test.py", line 6, in <module>
print(msg)
NameError: name 'msg' is not defined
msg
in the except clause is in the same scope as msg
on the first line.
But in Python 3 we have this new behavior too:
When an exception has been assigned using
as target
, it is cleared at the end of the except clause. This is as ifexcept E as N: foo
was translated to
except E as N: try: foo finally: del N
This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
so, you "overwrite msg
" in the exception handler, and exiting the handler will delete the variable to clear the traceback reference cycle.