e-satis e-satis - 4 months ago 12
Python Question

Why can't pdb access a variable containing an exception?

Sometime, I can't identify when or what's causing it, pdb will not help you with code like:

try:
foo()
except Exception as e:
import pdb; pdb.set_trace()


You end up with the usual prompt, but trying to access
e
will lead to:

(pdb) e
*** NameError: name 'e' is not defined.


It's not all the time of course, and it happens on linux, windows, my machine, my colleague machine...

Answer

In Python 3, the target of an except .. as target statement is cleared when the suite exits. From the try statement documentation:

When an exception has been assigned using as target, 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 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.

Calling pdb.set_trace() effectively exits the block, so the implicit finally suite above is executed.

Bind the exception to a different name:

try:
    foo()
except Exception as e:
   exception = e
   import pdb; pdb.set_trace()

Demo:

>>> try:
...     foo()
... except Exception as e:
...    exception = e
...    import pdb; pdb.set_trace()
...
--Return--
> <stdin>(5)<module>()->None
(Pdb) e
*** NameError: name 'e' is not defined
(Pdb) exception
NameError("name 'foo' is not defined",)