Site Section:
Keywords:
I am afraid that in practice I have always ended up going the simple "litter the code with print statements" route when debugging my Python. Without the compilation step, the cost of inserting and then removing these lines from the source code is relatively cheap, and has served me well enough so far. Thus, as sanctioned under the "if it is not broken, don't fix it" clause, I have not felt the need to look any further, or look into learning how to use pdb. If I used a bells-and-whistles glamorous IDE for development (e.g., WinPDB, PyCharm, WingIDE), I probably would take advantage of the built-in visually-oriented debuggers. But right now, I use Vim as my main development environment, and I doubt that is going to change anytime soon. So, it seemed that print-statement based debugging was going to be around for a while to come.
Until, that is, I learned how easy using pdb actually is. It takes just the following inserted into the desired breakpoint(s) in your code:
import pdb; pdb.set_trace();
That's it.
That's all there is to it.
Just that one line of code -- barely more characters then a minimal print statement -- and you are in the debugging business: the execution breaks right there, and you are dropped into a deugger shell. This shell is a slightly-limited Python REPL interpreter shell enhanced with all the usual debugging commands (step, continue, bt, etc.) . It is limited in comparison to the full-fledged Python REPL interpreter shell in that multi-line statements are not possible, and some names are now used as the built-in debugger commands (which can be seen by typing '?' or 'help').
Knowing how simple pdb-based debugging is, I think I am going to be using it a lot more in the future. One little plus is that there is not much chance that the character sequence "pdb.set_trace()" plays a role in production code, so you can safely and easily strip out the debugging code in Vim by the following command:
:g /pdb\.set_trace()/d
As a bonus nugget of info, I also learned that if I wanted to invoke the full-fledged Python REPL shell anywhere in my code, all I have to do is insert:
import code; code.interact(local=locals());
at the appropriate point. Exiting the shell will resume execution of the program.
feed
12 Comments
I often put "from pdb import
Submitted by Keith (not verified) on
I often put "from pdb import set_trace as brake" at the top of a file I'm working on. That way I can just put "brakepoints" in (break is a reserved word), and it's much easier to type "brake()" than "import pdb; pdb.set_trace()" whenever I want to set a breakpoint. Also, thanks for reminding me about code.interact.
Nice
Submitted by Jeet Sukumaran on
Nice suggestion. We could go one step further and do something like "from pdb import set_trace as _DEBUG", or some such, which would also make the breakpoints easy to spot visually when scanning code.
ipdb
Submitted by Julien (not verified) on
http://pypi.python.org/pypi/ipdb
or
https://github.com/narfdotpl/debug
ipdb is great!
Submitted by Jeet Sukumaran on
Thanks for pointing that out!
Why does your python code
Submitted by chewxy (not verified) on
Why does your python code have semicolons?
So that the import and method
Submitted by Jeet Sukumaran on
This is the usage shown in the official Python documentation (http://docs.python.org/library/pdb.html). The reason (in my case, at least, and probably that in the Python docs) is that the import and method call can be placed on one line, making both insertion and removal of the debugging code easy (and even partially automatable). It does not make it to production code. Remember: foolish consistency is the hobgoblin of little minds (PEP-8).
From Ipython
Submitted by Jorgen (not verified) on
I use Vim + Ipython and I love it. The Ipython debugger has pretty colors. I put the following in my scripts up where the imports are:
def run_from_ipython():
try:
__IPYTHON__
return True
except NameError:
return False
if run_from_ipython():
from IPython.Debugger import Tracer
debug = Tracer()
else:
def debug():
print ('Warning: debugging mark present.')
pass
Now I just write "debug()" wherever I want to enter the debugger. The cool thing about the ipython debugger is that it has tab-completion of names and class attributes.
Graphical debuggers are good for newbies and overviews
Submitted by Chris Lasher (not verified) on
Although I can appreciate the minimality of dropping into a console-based debugger like pdb, there's a lot to be said about using graphical debuggers. For one, they are much more immediately approachable for novice programmers who have not used debuggers before. To this end, I wrote a full tutorial for WinPDB that takes under an hour to work through.
On top of that, the ability to simultaneously display all variables and their values in a given context without having to explicitly request the debugger to print out each can save a lot of time and keystrokes. Often when I begin debugging, I do not know exactly which variable I should be monitoring, if even the scope. A graphical debugger like WinPDB means that I don't have to take wild guesses but can get an overview of the entire variable space once I reach my breakpoint with only a glance or maybe a few mouse clicks.
Shorter Vim sequence to delete pdb statement
Submitted by Michael Henry (not verified) on
Instead of this Vim sequence to remove the set_trace calls:
:g /pdb\.set_trace()/normal! Vd
You could use this shorter invocation:
:g /pdb\.set_trace()/d
The ex-mode command :d deletes a line, so you don't need
the more verbose "normal! Vd". See more information at:
:help :d
As another example, I frequently use the :g//d idiom for deleting blank lines:
:g/^\s*$/d
Thanks for the interesting post.
Thanks for that!
Submitted by Jeet Sukumaran on
Thanks for pointing that out. There's always something new to learn about Vim, and it always gets better!
:g/re/d?
Submitted by Marius Gedminas (not verified) on
Why would you use
:g /pdb\.set_trace()/normal! Vd
when
:g /pdb\.set_trace()/d
does the same and is much simpler? Am I missing something?
Alternative: invoking PDB from the command line
Submitted by xtian (not verified) on
You can also run a Python program under the debugger by running it like so:
python -m pdb your_file.py [arguments as normal]
It will break before running and you can create breakpoints with the normal commands:
break [filepath]:[line]
As well as not requiring you to change the source to add the breakpoint (which can escape into production!), it means that you can disable the breakpoint during the debugging session.
Additionally, you can put the breakpoint commands (or any other PDB commands) in a .pdbrc file in the current directory or in your home directory.
Add new comment