3

Why the variable used in the except statement is removed? I mean doing:

x = 0

try:
  x = 5/0
except ZeroDivisionError as x:
  pass

print(x)

I get NameError: name 'x' is not defined why this? Couldn't it work as with def or comprehensions where if there is a variable with same name of a variable in the enclosing function (or module) it is simply shadowed but not removed?

zer0uno
  • 7,521
  • 13
  • 57
  • 86

2 Answers2

4

The behavior is documented here:

When an exception has been assigned using as target, it is cleared at the end of the except clause.

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.

Community
  • 1
  • 1
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
4

This is explained in the documentation (parts in [ ] braces added by me):

When an exception has been assigned using as target [i.e. as x in your case], it is cleared at the end of the except clause. This is as if

except 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 [i.e. this name, x in your case] after the except clause.

The reason for this is also stated:

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.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130