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.
-
If you use `IPython`, it's much simpler. `ipython --pdb myscript.py` – John Strood Jan 20 '22 at 08:26
-
1If you don't, then `python -m pdb -c cont myscript.py` (Elaborated in one of the answers below). – John Strood Jan 20 '22 at 08:32
-
3You could also replace it with `ipdb`, `python -m ipdb -c cont myscript.py` – John Strood Jan 20 '22 at 08:33
15 Answers
python -m pdb -c continue myscript.py
# or
python -m pdb -c continue -m myscript
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).

- 3,005
- 9
- 52
- 119

- 7,383
- 2
- 25
- 17
-
1Wow, thanks! If now this initial call of PDB could also be avoided things would be perfect. Any ideas? – flonk Apr 04 '13 at 09:24
-
10Thanks for mentioning the "_enter 'c'_" - I typically used to enter 'r' (for "run"), being used to it from `gdb`; and when you enter 'r' in `pdb`, program does indeed run, but does NOT stop (nor generate backtrace) on error; had me puzzled until I read this. Cheers! – sdaau Aug 02 '13 at 20:58
-
4I tried your method. But it doesn't seem to offer any real control like inspecting variables at the the time of error. The only option it seems to offer is to restart execution. – Flame of udun Dec 07 '14 at 02:44
-
3Vineet, it will start you with the debugger on, so enter "cont" and it will run until the error is encountered. From there you can inspect variables, etc. like in any other pdb session. – Catherine Devlin Dec 17 '14 at 16:41
-
67Please OP, accept this as an answer. This is the most useful and I have wasted 5 minutes reading the other ones until I hit this one... this should be first ! – jhegedus Sep 17 '15 at 19:46
-
5This also works the same with `ipdb`; and of course arguments can be added after the script! – tutuDajuju Dec 14 '15 at 10:03
-
This is the answer I was looking for. The accepted answer requires adding code just to launch a debug session, which is highly inconvenient. – Moises Silva Jan 27 '16 at 17:09
-
1OP, please don't accept this as an answer. This does not work for KeyError, for example. It starts a debugger session in the beginning of the script again, and not in the line of the error. The selected answer (type, value, tb = sys.exc_info() + traceback.print_exc() + pdb.post_mortem(tb) ) is the right one. – corporateAbaper Aug 04 '16 at 10:44
-
@tutuDajuju, how do you get this to work with `ipdb`? I tried simply changing `pdb` in the above command to `ipdb`, but it gave me an error saying that "-c does not exist." – Vivek Subramanian Mar 07 '17 at 18:23
-
@vivek seems this was [fixed recently](https://github.com/gotcha/ipdb/commit/2381b128f5c62a0426e16465bfb9f86295dd7b94) but was not yet released to pypi. – tutuDajuju Mar 07 '17 at 19:25
-
21This doesn't work with Python 2.7. https://docs.python.org/3/library/pdb.html : "New in version 3.2: pdb.py now accepts a -c option that executes commands" – eqzx Apr 10 '17 at 18:29
-
1@eqzx The rest of the answer remains valid. We only have to hit 'c' after execution ... the rest is fine! – AruniRC Dec 19 '17 at 15:27
-
1and do `pip install pdbpp` before using above, for nicer the UI. – Sławomir Lenart Feb 12 '19 at 16:04
-
1@eqzx one solution to not having the `-c` flag in Python 2.7 is `(echo c && cat) | python -pdb script.py` – Ben Usman Mar 21 '19 at 19:26
-
1https://stackoverflow.com/a/242531/237059 more accurately responds to the exact OP request -- they're not asking "how can I wrap the whole app in the debugger all the time?" – Stabledog Nov 21 '19 at 18:30
-
1
-
the need for `-c continue` seems rather strange or redudant...why is that formally needed? why does pdb not just do it out of the box? Also why do you need the `-m` flag? – Charlie Parker Jun 29 '22 at 18:29
-
btw mentioning `ipython --pdb myscript.py` and the other options you mentioned could be nice – Charlie Parker Jun 29 '22 at 18:29
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)

- 4,271
- 8
- 34
- 56

- 27,420
- 11
- 48
- 53
-
the first solution is further discussed at the [python cookbook](http://code.activestate.com/recipes/65287-automatically-start-the-debugger-on-an-exception/) – dirkjot Jun 27 '12 at 20:12
-
4why would anyone prefer `code` over `pdb` since the latter seems to expand on the former? – K3---rnc Aug 25 '14 at 21:49
-
-
4*Then use `sys.exc_info` to extract the traceback and finally call `pdb.post_mortem` with that traceback*. You don't need to pass traceback object to `pdb.post_mortem`. From [docs](https://docs.python.org/2/library/pdb.html): *If no traceback is given, it uses the one of the exception that is currently being handled (an exception must be being handled if the default is to be used).* – Piotr Dobrogost Apr 21 '15 at 08:13
-
2@PiotrDobrogost Good point. I think it's more helpful to know that you can pass a tb object in, though, as it better demonstrates the API. Good to know both options exist. – davidA Dec 18 '16 at 23:35
-
I'm putting these snippets in context managers in my util.py -- https://pastebin.com/7rC8EsuC – loxaxs May 16 '18 at 09:17
-
Is this as good as Common Lisp's restart system? Say you wrote "5" + num when you meant to write "5" + str(num), is it possible after doing post_mortem to fix your bug then continue off as if nothing happened? – aoeu256 Sep 16 '19 at 05:41
-
1Regarding "why would you prefer code over pdb on the command line?" -- there are contexts where the interpreter is launched from within a process that doesn't allow you to launch the debugger as a wrapper... e.g. when the interpreter is just part of a larger application or some framework is managing a complex environment surrounding the interpreter. In such cases, doing a stub launcher like this makes sense. – Stabledog Oct 30 '19 at 18:45
-
@aoeu256 PyTrace https://pytrace.com/ time travelling debugger can step back and alter things like the CL frame restart system – ocodo May 17 '23 at 15:59
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
.
-
4This should be the accepted answer -- it doesn't require any modification of existing code or wrapping everything in a `try-catch` which is just ugly IMO. – cyphar Sep 07 '15 at 15:01
-
1This looks great, but note that some frameworks (e.g. flask) already set `sys.excepthook`. They often have their own even better approaches like werkzeug, but see also [python - Flask and sys\.excepthook - Stack Overflow](https://stackoverflow.com/questions/21627429/flask-and-sys-excepthook) – nealmcb Nov 06 '20 at 02:11
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!

- 2,553
- 2
- 23
- 21
-
6
-
7Documented at http://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-pdb – matthiash Mar 03 '17 at 14:38
-
8Note that -- as also noted in the docs @matthiash linked -- `%debug` allows one to open the debugger _after_ encountering an error. I often prefer this over `%pdb`. (The trade-off is merely typing `q` every time you don't want to debug an error vs. typing `%debug` every time you _do_ want to debug an error.) – Braham Snyder Oct 29 '17 at 21:12
-
3Note also that setting `c.InteractiveShell.pdb = True` in one's `ipython_config.py` turns on `%pdb` automatically for every session. – Braham Snyder Oct 29 '17 at 21:17
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.

- 42,176
- 24
- 124
- 155
-
-
10Not nearly as useful, launches into global scope. Can't poke around in whatever function crashed. – pixelpax Mar 26 '16 at 20:37
-
how could this be made so it only goes into 'debug' if there was an error. – MarioTheHedgehog Aug 27 '20 at 14:53
-
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.

- 3,871
- 5
- 33
- 45
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.

- 414
- 4
- 13
-
Note that if the error occurred in a module function, you can navigate through the frames with `up` and `down` commands to go back to the line of your code that generated the error. – Jean Paul Jan 23 '19 at 10:23
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.

- 93
- 1
- 5
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.

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

- 39
- 1
You can put this line in your code:
import pdb ; pdb.set_trace()
More info: Start the python debugger at any line

- 58,203
- 71
- 188
- 248
-
11This stops the code and starts a debugger in the line where you put this command, not on the line where an exception occurred – blueFast Feb 18 '16 at 17:53
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()

- 317
- 2
- 6
If you happen to be using pudb (python debugger with a nice interface), you can enter debugger when an exception occurs with:
python -m pudb -c code_that_crashes.py
pudb describes the -c
option as:
-c, --continue Let the script run until an exception occurs or a breakpoint is hit

- 529
- 6
- 10
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

- 7,480
- 15
- 80
- 124