The PythonDebuggingTools documentation says that the Python debugger pdb is "part of all Python installations", yet I can't find it under macOS High Sierra:
pdb: command not found
Is it supposed to be installed as normal part of macOS these days?
There is not a command named pdb, but you could invoke pdb from shell with:
python -m pdb your_script.py
you could read more methods to invoke pdb in its doc.
if you use IPython the debugger can be invoked by using
IPython 6.2.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: %pdb
Automatic pdb calling has been turned ON
In [2]: %pdb
Automatic pdb calling has been turned OFF
In [3]: ?pdb
Docstring:
Control the automatic calling of the pdb interactive debugger.
Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
argument it works as a toggle.
When an exception is triggered, IPython can optionally call the
interactive pdb debugger after the traceback printout. %pdb toggles
this feature on and off.
The initial state of this feature is set in your configuration
file (the option is ``InteractiveShell.pdb``).
If you want to just activate the debugger AFTER an exception has fired,
without having to type '%pdb on' and rerunning your code, you can use
the %debug magic.
File: ~/anaconda/envs/py36/lib/python3.6/site-packages/IPython/core/magics/execution.py
You may need to install IPython with either pip or conda.
Is there a way to run a script in iPyton with the %run myscript.py so that it will take into consideration the things I have already entered in the interactive iPython console?
Example:
In [1]: asdf = 18
In [2]:
Then if myscript.py was:
print asdf
And it was ran from iPython like this:
In [2]: %run myscript.py
18
In [3]:
Can this be done?
Try using the %load magic function, available in the IPython Notebook (qtconsole or web version). It allows you to load the contents of a file into a cell, edit them if you want, then run them in the current context.
Use %logstart/%logon and %logstop/%logoff. With these controls, you will have a python_log.py file that stores your history.
I have noticed that some of the ipython functionality is not available from the debugger. For example, the ? and ?? operands for variable introspection don't work:
e.g.
ipython> run my_script.py
ipython> %debug
ipdb> foo?
*** SyntaxError: invalid syntax(<stdin>, line1)
Is there a way to bring the full ipython functionality to the debugger?
ipython runs Python debugger pdb for debugging, so you are limited to commands offered by pdb (type h for a list) plus standard Python syntax (you may replace foo? with help(foo)).
If you want to start IPython shell at an arbitrary position in your code you can try Embedding IPython.
In Java/C# you can easily step through code to trace what might be going wrong, and IDE's make this process very user friendly.
Can you trace through python code in a similar fashion?
Yes! There's a Python debugger called pdb just for doing that!
You can launch a Python program through pdb by using pdb myscript.py or python -m pdb myscript.py.
There are a few commands you can then issue, which are documented on the pdb page.
Some useful ones to remember are:
b: set a breakpoint
c: continue debugging until you hit a breakpoint
s: step through the code
n: to go to next line of code
l: list source code for the current file (default: 11 lines including the line being executed)
u: navigate up a stack frame
d: navigate down a stack frame
p: to print the value of an expression in the current context
If you don't want to use a command line debugger, some IDEs like Pydev, Wing IDE or PyCharm have a GUI debugger. Wing and PyCharm are commercial products, but Wing has a free "Personal" edition, and PyCharm has a free community edition.
By using Python Interactive Debugger 'pdb'
First step is to make the Python interpreter to enter into the debugging mode.
A. From the Command Line
Most straight forward way, running from command line, of python interpreter
$ python -m pdb scriptName.py
> .../pdb_script.py(7)<module>()
-> """
(Pdb)
B. Within the Interpreter
While developing early versions of modules and to experiment it more iteratively.
$ python
Python 2.7 (r27:82508, Jul 3 2010, 21:12:11)
[GCC 4.0.1 (Apple Inc. build 5493)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pdb_script
>>> import pdb
>>> pdb.run('pdb_script.MyObj(5).go()')
> <string>(1)<module>()
(Pdb)
C. From Within Your Program
For a big project and long-running module, can start the debugging from inside the program using
import pdb and set_trace()
like this :
#!/usr/bin/env python
# encoding: utf-8
#
import pdb
class MyObj(object):
count = 5
def __init__(self):
self.count= 9
def go(self):
for i in range(self.count):
pdb.set_trace()
print i
return
if __name__ == '__main__':
MyObj(5).go()
Step-by-Step debugging to go into more internal
Execute the next statement… with “n” (next)
Repeating the last debugging command… with ENTER
Quitting it all… with “q” (quit)
Printing the value of variables… with “p” (print)
a) p a
Turning off the (Pdb) prompt… with “c” (continue)
Seeing where you are… with “l” (list)
Stepping into subroutines… with “s” (step into)
Continuing… but just to the end of the current subroutine… with “r” (return)
Assign a new value
a) !b = "B"
Set a breakpoint
a) break linenumber
b) break functionname
c) break filename:linenumber
Temporary breakpoint
a) tbreak linenumber
Conditional breakpoint
a) break linenumber, condition
Note:**All these commands should be execute from **pdb
For in-depth knowledge, refer:-
https://pymotw.com/2/pdb/
https://pythonconquerstheuniverse.wordpress.com/2009/09/10/debugging-in-python/
There is a module called 'pdb' in python. At the top of your python script you do
import pdb
pdb.set_trace()
and you will enter into debugging mode. You can use 's' to step, 'n' to follow next line similar to what you would do with 'gdb' debugger.
Starting in Python 3.7, you can use the breakpoint() built-in function to enter the debugger:
foo()
breakpoint() # drop into the debugger at this point
bar()
By default, breakpoint() will import pdb and call pdb.set_trace(). However, you can control debugging behavior via sys.breakpointhook() and use of the environment variable PYTHONBREAKPOINT.
See PEP 553 for more information.
ipdb (IPython debugger)
ipdb adds IPython functionality to pdb, offering the following HUGE improvements:
tab completion
show more context lines
syntax highlight
Much like pdg, ipdb is still far from perfect and completely rudimentary if compared to GDB, but it is already a huge improvement over pdb.
Usage is analogous to pdb, just install it with:
python3 -m pip install --user ipdb
and then add to the line you want to step debug from:
__import__('ipdb').set_trace(context=21)
You likely want to add a shortcut for that from your editor, e.g. for Vim snipmate I have:
snippet ipd
__import__('ipdb').set_trace(context=21)
so I can type just ipd<tab> and it expands to the breakpoint. Then removing it is easy with dd since everything is contained in a single line.
context=21 increases the number of context lines as explained at: How can I make ipdb show more lines of context while debugging?
Alternatively, you can also debug programs from the start with:
ipdb3 main.py
but you generally don't want to do that because:
you would have to go through all function and class definitions as Python reads those lines
I don't know how to set the context size there without hacking ipdb. Patch to allow it: https://github.com/gotcha/ipdb/pull/155
Or alternatively, as in raw pdb 3.2+ you can set some breakpoints from the command line:
ipdb3 -c 'b 12' -c 'b myfunc' ~/test/a.py
although -c c is broken for some reason: https://github.com/gotcha/ipdb/issues/156
python -m module debugging has been asked at: How to debug a Python module run with python -m from the command line? and since Python 3.7 can be done with:
python -m pdb -m my_module
Serious missing features of both pdb and ipdb compared to GDB:
persistent command history across sessions: Save command history in pdb
ipdb specific annoyances:
multithreading does not work well if you don't hack some settings...
ipdb, multiple threads and autoreloading programs causing ProgrammingError
https://github.com/gotcha/ipdb/issues/51
Tested in Ubuntu 16.04, ipdb==0.11, Python 3.5.2.
VSCode
If you want to use an IDE, this is a good alternative to PyCharm.
Install VSCode
Install the Python extension, if it's not already installed
Create a file mymodule.py with Python code
To set a breakpoint, hover over a line number and click the red dot, or press F9
Hit F5 to start debugging and select Python File
It will stop at the breakpoint and you can do your usual debugging stuff like inspecting the values of variables, either at the tab VARIABLES (usually on the left) or by clicking on Debug Console (usually at the bottom next to your Terminal):
This screenshot shows VSCodium.
More information
Python debugging in VS Code
Getting Started with Python in VS Code
Debugging in Visual Studio Code
There exist breakpoint() method nowadays, which replaces import pdb; pdb.set_trace().
It also has several new features, such as possible environment variables.
Python Tutor is an online single-step debugger meant for novices. You can put in code on the edit page then click "Visualize Execution" to start it running.
Among other things, it supports:
hiding variables, e.g. to hide a variable named x, put this at the end:
#pythontutor_hide: x
saving/sharing
a few other languages like Java, JS, Ruby, C, C++
However it also doesn't support a lot of things, for example:
Reading/writing files - use io.StringIO and io.BytesIO instead: demo
Code that is too large, runs too long, or defines too many variables or objects
Command-line arguments
Lots of standard library modules like argparse, csv, enum, html, os, sys, weakref...
Python 3.7+
Let's take look at what breakpoint() can do for you in 3.7+.
I have installed ipdb and pdbpp, which are both enhanced debuggers, via
pip install pdbpp
pip install ipdb
My test script, really doesn't do much, just calls breakpoint().
#test_188_breakpoint.py
myvars=dict(foo="bar")
print("before breakpoint()")
breakpoint() # 👈
print(f"after breakpoint myvars={myvars}")
breakpoint() is linked to the PYTHONBREAKPOINT environment variable.
CASE 1: disabling breakpoint()
You can set the variable via bash as usual
export PYTHONBREAKPOINT=0
This turns off breakpoint() where it does nothing (as long as you haven't modified sys.breakpointhook() which is outside of the scope of this answer).
This is what a run of the program looks like:
(venv38) myuser#explore$ export PYTHONBREAKPOINT=0
(venv38) myuser#explore$ python test_188_breakpoint.py
before breakpoint()
after breakpoint myvars={'foo': 'bar'}
(venv38) myuser#explore$
Didn't stop, because I disabled breakpoint. Something that pdb.set_trace() can't do 😀😀😀!
CASE 2: using the default pdb behavior:
Now, let's unset PYTHONBREAKPOINT which puts us back to normal, enabled-breakpoint behavior (it's only disabled when 0 not when empty).
(venv38) myuser#explore$ unset PYTHONBREAKPOINT
(venv38) myuser#explore$ python test_188_breakpoint.py
before breakpoint()
[0] > /Users/myuser/kds2/wk/explore/test_188_breakpoint.py(6)<module>()
-> print(f"after breakpoint myvars={myvars}")
(Pdb++) print("pdbpp replaces pdb because it was installed")
pdbpp replaces pdb because it was installed
(Pdb++) c
after breakpoint myvars={'foo': 'bar'}
It stopped, but I actually got pdbpp because it replaces pdb entirely while installed. If I unistalled pdbpp, I'd be back to normal pdb.
Note: a standard pdb.set_trace() would still get me pdbpp
CASE 3: calling a custom debugger
But let's call ipdb instead. This time, instead of setting the environment variable, we can use bash to set it only for this one command.
(venv38) myuser#explore$ PYTHONBREAKPOINT=ipdb.set_trace py test_188_breakpoint.py
before breakpoint()
> /Users/myuser/kds2/wk/explore/test_188_breakpoint.py(6)<module>()
5 breakpoint()
----> 6 print(f"after breakpoint myvars={myvars}")
7
ipdb> print("and now I invoked ipdb instead")
and now I invoked ipdb instead
ipdb> c
after breakpoint myvars={'foo': 'bar'}
Essentially, what it does, when looking at $PYTHONBREAKPOINT:
from ipdb import set_trace # function imported on the right-most `.`
set_trace()
Again, much cleverer than a plain old pdb.set_trace() 😀😀😀
in practice? I'd probably settle on a debugger.
Say I want ipdb always, I would:
export it via .profile or similar.
disable on a command by command basis, without modifying the normal value
Example (pytest and debuggers often make for unhappy couples):
(venv38) myuser#explore$ export PYTHONBREAKPOINT=ipdb.set_trace
(venv38) myuser#explore$ echo $PYTHONBREAKPOINT
ipdb.set_trace
(venv38) myuser#explore$ PYTHONBREAKPOINT=0 pytest test_188_breakpoint.py
=================================== test session starts ====================================
platform darwin -- Python 3.8.6, pytest-5.1.2, py-1.9.0, pluggy-0.13.1
rootdir: /Users/myuser/kds2/wk/explore
plugins: celery-4.4.7, cov-2.10.0
collected 0 items
================================== no tests ran in 0.03s ===================================
(venv38) myuser#explore$ echo $PYTHONBREAKPOINT
ipdb.set_trace
p.s.
I'm using bash under macos, any posix shell will behave substantially the same. Windows, either powershell or DOS, may have different capabilities, especially around PYTHONBREAKPOINT=<some value> <some command> to set a environment variable only for one command.
If you come from Java/C# background I guess your best bet would be to use Eclipse with Pydev. This gives you a fully functional IDE with debugger built in. I use it with django as well.
https://wiki.python.org/moin/PythonDebuggingTools
pudb is a good drop-in replacement for pdb
PyCharm is an IDE for Python that includes a debugger. Watch this YouTube video for an introduction on using it to step through code:
PyCharm Tutorial - Debug python code using PyCharm (the debugging starts at 6:34)
Note: PyCharm is a commercial product, but the company does provide a free license to students and teachers, as well as a "lightweight" Community version that is free and open-source.
If you want an IDE with integrated debugger, try PyScripter.
Programmatically stepping and tracing through python code is possible too (and its easy!). Look at the sys.settrace() documentation for more details. Also here is a tutorial to get you started.
Visual Studio with PTVS could be an option for you: http://www.hanselman.com/blog/OneOfMicrosoftsBestKeptSecretsPythonToolsForVisualStudioPTVS.aspx
For my debugging needs, pdb is pretty good. However, it would be much cooler (and helpful) if I could go into ipython. Is this thing possible?
There is an ipdb project which embeds iPython into the standard pdb, so you can just do:
import ipdb; ipdb.set_trace()
It's installable via the usual pip install ipdb.
ipdb is pretty short, so instead of easy_installing you can also create a file ipdb.py somewhere on your Python path and paste the following into the file:
import sys
from IPython.Debugger import Pdb
from IPython.Shell import IPShell
from IPython import ipapi
shell = IPShell(argv=[''])
def set_trace():
ip = ipapi.get()
def_colors = ip.options.colors
Pdb(def_colors).set_trace(sys._getframe().f_back)
In IPython 0.11, you can embed IPython directly in your code like this
Your program might look like this
In [5]: cat > tmpf.py
a = 1
from IPython import embed
embed() # drop into an IPython session.
# Any variables you define or modify here
# will not affect program execution
c = 2
^D
This is what happens when you run it (I arbitrarily chose to run it inside an existing ipython session. Nesting ipython sessions like this in my experience can cause it to crash).
In [6]:
In [6]: run tmpf.py
Python 2.7.2 (default, Aug 25 2011, 00:06:33)
Type "copyright", "credits" or "license" for more information.
IPython 0.11 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: who
a embed
In [2]: a
Out[2]: 1
In [3]:
Do you really want to exit ([y]/n)? y
In [7]: who
a c embed
If you're using a more modern version of IPython (> 0.10.2) you can use something like
from IPython.core.debugger import Pdb
Pdb().set_trace()
But it's probably better to just use ipdb
The equivalent of
import pdb; pdb.set_trace()
with IPython is something like:
from IPython.ipapi import make_session; make_session()
from IPython.Debugger import Pdb; Pdb().set_trace()
It's a bit verbose, but good to know if you don't have ipdb installed. The make_session call is required once to set up the color scheme, etc, and set_trace calls can be placed anywhere you need to break.
Normally, when I use ipython, I turn automatic debugging on with the "pdb" command inside it.
I then run my script with the "run myscript.py" command in the directory where my script is located.
If I get an exception, ipython stops the program inside the debugger. Check out the help command for the magic ipython commands (%magic)
I like to simply paste this one-liner in my scripts where I want to set a breakpoint:
__import__('IPython').Debugger.Pdb(color_scheme='Linux').set_trace()
Newer version might use:
__import__('IPython').core.debugger.Pdb(color_scheme='Linux').set_trace()
Looks like modules have been shuffled around a bit recently. On IPython 0.13.1 the following works for me
from IPython.core.debugger import Tracer; breakpoint = Tracer()
breakpoint() # <= wherever you want to set the breakpoint
Though alas, it's all pretty worthless in qtconsole.
Newer versions of IPython provide an easy mechanism for embedding and nesting IPython sessions into any Python programs. You can follow the following recipe to embed IPython sessions:
try:
get_ipython
except NameError:
banner=exit_msg=''
else:
banner = '*** Nested interpreter ***'
exit_msg = '*** Back in main IPython ***'
# First import the embed function
from IPython.frontend.terminal.embed import InteractiveShellEmbed
# Now create the IPython shell instance. Put ipshell() anywhere in your code
# where you want it to open.
ipshell = InteractiveShellEmbed(banner1=banner, exit_msg=exit_msg)
Then use ipshell() whenever you want to drop into an IPython shell. This will allow you to embed (and even nest) IPython interpreters in your code.
From the IPython docs:
import IPython.ipapi
namespace = dict(
kissa = 15,
koira = 16)
IPython.ipapi.launch_new_instance(namespace)
will launch an IPython shell programmatically. Obviously the values in the namespace dict are just dummy values - it might make more sense to use locals() in practice.
Note that you have to hard-code this in; it's not going to work the way pdb does. If that's what you want, DoxaLogos' answer is probably more like what you're looking for.
The fast-and-easy way:
from IPython.Debugger import Tracer
debug = Tracer()
Then just write
debug()
wherever you want to start debugging your program.
I had to google this a couple if times the last few days so adding an answer... sometimes it's nice to be able run a script normally and only drop into ipython/ipdb on errors, without having to put ipdb.set_trace() breakpoints into the code
ipython --pdb -c "%run path/to/my/script.py --with-args here"
(first pip install ipython and pip install ipdb of course)
This is pretty simple:
ipython some_script.py --pdb
It needs iPython installing, usually this works:
pip install ipython
I use ipython3 instead of ipython, so I know it's a recent version of Python.
This is simple to remember because you just use iPython instead of python, and add --pdb to the end.
To get IPython's REPL using terminal colors, I had to do this:
from IPython import start_ipython
start_ipython()
https://ipython.readthedocs.io/en/stable/api/generated/IPython.html#IPython.start_ipython