Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Starting python debugger automatically on error

People also ask

How do I start Python in debug mode?

Starting Python Debugger 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().

Can I debug Python in idle?

To do so, select Debug → Debugger from the Python IDLE menu bar. In the interpreter, you should see [DEBUG ON] appear just before the prompt ( >>> ), which means the interpreter is ready and waiting. In this window, you can inspect the values of your local and global variables as your code executes.

What is pdb Python?

The module pdb defines an interactive source code debugger for Python programs. It supports setting (conditional) breakpoints and single stepping at the source line level, inspection of stack frames, source code listing, and evaluation of arbitrary Python code in the context of any stack frame.


python -m pdb -c continue myscript.py

If you don't provide the -c continue flag then you'll need to enter 'c' (for Continue) when execution begins. Then it will run to the error point and give you control there. As mentioned by eqzx, this flag is a new addition in python 3.2 so entering 'c' is required for earlier Python versions (see https://docs.python.org/3/library/pdb.html).


You can use traceback.print_exc to print the exceptions traceback. Then use sys.exc_info to extract the traceback and finally call pdb.post_mortem with that traceback

import pdb, traceback, sys

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        extype, value, tb = sys.exc_info()
        traceback.print_exc()
        pdb.post_mortem(tb)

If you want to start an interactive command line with code.interact using the locals of the frame where the exception originated you can do

import traceback, sys, code

def bombs():
    a = []
    print a[0]

if __name__ == '__main__':
    try:
        bombs()
    except:
        type, value, tb = sys.exc_info()
        traceback.print_exc()
        last_frame = lambda tb=tb: last_frame(tb.tb_next) if tb.tb_next else tb
        frame = last_frame().tb_frame
        ns = dict(frame.f_globals)
        ns.update(frame.f_locals)
        code.interact(local=ns)

Use the following module:

import sys

def info(type, value, tb):
    if hasattr(sys, 'ps1') or not sys.stderr.isatty():
    # we are in interactive mode or we don't have a tty-like
    # device, so we call the default hook
        sys.__excepthook__(type, value, tb)
    else:
        import traceback, pdb
        # we are NOT in interactive mode, print the exception...
        traceback.print_exception(type, value, tb)
        print
        # ...then start the debugger in post-mortem mode.
        # pdb.pm() # deprecated
        pdb.post_mortem(tb) # more "modern"

sys.excepthook = info

Name it debug (or whatever you like) and put it somewhere in your python path.

Now, at the start of your script, just add an import debug.


Ipython has a command for toggling this behavior: %pdb. It does exactly what you described, maybe even a bit more (giving you more informative backtraces with syntax highlighting and code completion). It's definitely worth a try!


This isn't the debugger, but probably just as useful(?)

I know I heard Guido mention this in a speech somewhere.

I just checked python -?, and if you use the -i command you can interact where your script stopped.

So given this script:

testlist = [1,2,3,4,5, 0]

prev_i = None
for i in testlist:
    if not prev_i:
        prev_i = i
    else:
        result = prev_i/i

You can get this output!

PS D:\> python -i debugtest.py
Traceback (most recent call last):
  File "debugtest.py", line 10, in <module>
    result = prev_i/i
ZeroDivisionError: integer division or modulo by zero
>>>
>>>
>>> prev_i
1
>>> i
0
>>>

To be honest I haven't used this, but I should be, seems very useful.


IPython makes this simple on the command line:

python myscript.py arg1 arg2

can be rewritten to

ipython --pdb myscript.py -- arg1 arg2

Or, similarly, if calling a module:

python -m mymodule arg1 arg2

can be rewritten to

ipython --pdb -m mymodule -- arg1 arg2

Note the -- to stop IPython from reading the script's arguments as its own.

This also has the advantage of invoking the enhanced IPython debugger (ipdb) instead of pdb.


If you are using ipython, after launching type %pdb

In [1]: %pdb
Automatic pdb calling has been turned ON