My Python script is crashing. To debug it, I ran it in interactive mode python -i example.py
Traceback (most recent call last):
File "example.py", line 5, in <module>
main()
File "example.py", line 3, in main
message[20]
IndexError: string index out of range
At this point, I would like to inspect the variable message
. I tried
>>> message
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'message' is not defined
Alas message
is not in scope (though main
is). That's frustrating. How can I inspect the variable? Is there a more useful version of python -i
that keeps what's in scope at the crash (rather than the top level)?
Code used for example.py
above. Needless to say, this is a simplification.
def main():
message = "hello world"
message[20]
main()
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With