Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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...

like image 308
e-satis Avatar asked Jul 30 '16 09:07

e-satis


People also ask

How do you set a breakpoint in pdb?

Add import pdb; pdb. set_trace() at the corresponding line in the Python code and execute it. The execution will stop at the breakpoint. An interactive shell (the pdb shell) will appear and allows you to run regular Python code, i.e. to print the current contents of variables and data structures.

How do I debug Python code using pdb?

To start debugging within the program just insert import pdb, pdb. set_trace() commands. Run your script normally, and execution will stop where we have introduced a breakpoint. So basically we are hard coding a breakpoint on a line below where we call set_trace().

What is pdb Set_trace ()?

pdb. set_trace(*, header=None) Enter the debugger at the calling stack frame. This is useful to hard-code a breakpoint at a given point in a program, even if the code is not otherwise being debugged (e.g. when an assertion fails). If given, header is printed to the console just before debugging begins.


1 Answers

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",)
like image 185
Martijn Pieters Avatar answered Oct 14 '22 16:10

Martijn Pieters