Starting python debugger automatically on error

PythonDebugging

Python Problem Overview


This is a question I have wondered about for quite some time, yet I have never found a suitable solution. If I run a script and I come across, let's say an IndexError, python prints the line, location and quick description of the error and exits. Is it possible to automatically start pdb when an error is encountered? I am not against having an extra import statement at the top of the file, nor a few extra lines of code.

Python Solutions


Solution 1 - Python

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

Solution 2 - Python

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)

Solution 3 - Python

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.

Solution 4 - Python

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!

Solution 5 - Python

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.

Solution 6 - Python

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.

Solution 7 - Python

If you are using ipython, after launching type %pdb

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

Solution 8 - Python

If you are using the IPython environment, you can just use the %debug and the shell will take you back to the offending line with the ipdb environment for inspections etc. Another option as pointed above is to use the iPython magic %pdb which effectively does the same.

Solution 9 - Python

To have it run without having to type c at the beginning use:

python -m pdb -c c <script name>

Pdb has its own command line arguments: -c c will execute c(ontinue) command at start of execution and the program will run uninterrupted until the error.

Solution 10 - Python

python -m pdb script.py in python2.7 press continue to start and it will run to the error and break there for debug.

Solution 11 - Python

You can put this line in your code:

import pdb ; pdb.set_trace()

More info: http://www.technomancy.org/python/debugger-start-line/">Start the python debugger at any line

Solution 12 - Python

If you are running a module:

python -m mymodule

And now you want to enter pdb when an exception occurs, do this:

PYTHONPATH="." python -m pdb -c c mymodule/__main__.py

(or extend your PYTHONPATH). The PYTHONPATH is needed so that the module is found in the path, since you are running the pdb module now.

Solution 13 - Python

ipdb has a nice context manager to achieve this behavior which makes the intent semantically clearer:

from ipdb import launch_ipdb_on_exception

with launch_ipdb_on_exception():
    ...

Solution 14 - Python

Since 3.7, you can use the keyword breakpoint directly in your code (without any import), just like this:

try:
    ...  # The line that raises an error
except:
    breakpoint()

Solution 15 - Python

Put a breakpoint inside the constructor of topmost exception class in the hierarchy, and most of the times you will see where the error was raised.

Putting a breakpoint means whatever you want it to mean : you can use an IDE, or pdb.set_trace, or whatever

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionjeremyView Question on Stackoverflow
Solution 1 - PythonCatherine DevlinView Answer on Stackoverflow
Solution 2 - PythonFlorian BöschView Answer on Stackoverflow
Solution 3 - PythontzotView Answer on Stackoverflow
Solution 4 - PythonLataniusView Answer on Stackoverflow
Solution 5 - PythonmonkutView Answer on Stackoverflow
Solution 6 - PythonwodowView Answer on Stackoverflow
Solution 7 - PythonWillemoesView Answer on Stackoverflow
Solution 8 - PythonJehandadView Answer on Stackoverflow
Solution 9 - PythonZlatko KarakašView Answer on Stackoverflow
Solution 10 - PythonHannahView Answer on Stackoverflow
Solution 11 - PythonAmandasaurusView Answer on Stackoverflow
Solution 12 - PythonblueFastView Answer on Stackoverflow
Solution 13 - PythondlukesView Answer on Stackoverflow
Solution 14 - PythonJonathan DauweView Answer on Stackoverflow
Solution 15 - Pythonvlad-ardeleanView Answer on Stackoverflow