How to inspect variables after Traceback?
According to the Python docs https://docs.python.org/3.4/library/pdb.html
pdb.py
can also be invoked as a script to debug other scripts. For example:python -m pdb myscript.py
. When invoked as a script, pdb will automatically enter post-mortem debugging if the program being debugged exits abnormally.
This isn't entirely accurate. It actually enters debugging at the first line.
$ python -m pdb example.py
> example.py(1)<module>()
-> def main():
However if you type c
it will then continue to the crash
(Pdb) c
Traceback (most recent call last):
File "C:\Python34\lib\pdb.py", line 1661, in main
pdb._runscript(mainpyfile)
File "C:\Python34\lib\pdb.py", line 1542, in _runscript
self.run(statement)
File "C:\Python34\lib\bdb.py", line 431, in run
exec(cmd, globals, locals)
File "<string>", line 1, in <module>
File "example.py", line 1, in <module>
def main():
File "example.py", line 3, in main
message[20]
IndexError: string index out of range
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> example.py(3)main()
At this point you can type message
to inspect the variable.
-> message[20]
(Pdb) message
'hello world'
Wahey!
A simple alternative is to use cgitb module.
import cgitb; cgitb.enable(format='text')
def main():
message = "hello world"
message[20]
main()
Now the traceback itself prints the value of the message.
A problem occurred in a Python script. Here is the sequence of
function calls leading up to the error, in the order they occurred.
/home/anand/projects/python/ptb/tes.py in <module>()
4 def main():
5 message = "hello world"
6 message[20]
7
8 main()
main = <function main>
/home/anand/projects/python/ptb/tes.py in main()
4 def main():
5 message = "hello world"
6 message[20]
7
8 main()
message = 'hello world'
IndexError: string index out of range
To drop to a debugger only if there is an exception you could define a custom excepthook:
import sys
def excepthook(type_, value, tb):
import traceback
import pdb
traceback.print_exception(type_, value, tb)
pdb.post_mortem(tb)
sys.excepthook = excepthook
def main():
message = "hello world"
message[20]
main()
Running the script drops you into pdb and in the frame which raised the exception:
% script.py
Traceback (most recent call last):
File "/home/unutbu/pybin/script.py", line 16, in <module>
main()
File "/home/unutbu/pybin/script.py", line 14, in main
message[20]
IndexError: string index out of range
> /home/unutbu/pybin/script.py(14)main()
-> message[20]
(Pdb) p message
'hello world'
(Pdb) p message[20]
*** IndexError: IndexError('string index out of range',)
(Pdb) p len(message)
11
If defining the excepthook seems like too much code, you could tuck it away in a utility module, such as utils_debug.py:
import sys
def enable_pdb():
def excepthook(type_, value, tb):
import traceback
import pdb
traceback.print_exception(type_, value, tb)
pdb.post_mortem(tb)
sys.excepthook = excepthook
and then you would only need to add
import utils_debug as UDBG
UDBG.enable_pdb()
to your script.py
.
Or, if you are using IPython, you could use the %pdb magic function (which drops you into ipdb
when there is an exception).
It is unclear why inspecting size
at the pdb prompt is giving you a NameError. (A runnable example would be very useful.) You might try using bt
(backtrace) to inspect the frame stack. If size
is defined in a different frame than the one pdb
is currently in, you might be able use u
(up) to go up to the frame where size
is defined.