<< ALL BLOG POSTS

Debugging Python code with pdb

Table of Contents

The Python Debugger (pdb) is a powerful tool that all Python developers should be familiar with. It's an interactive debugger that you can start up anywhere in your codebase. This makes debugging complex or confusing code much simpler since you can interact directly with the code in a running state.

Basic Commands

There are just a few basic pdb commands you need to know in order to start being productive. If you want more info, you can always look at the internal help:

(Pdb) help
(Pdb) help list

The most basic commands you will need are list, next, step and continue. This will allow you to do basic navigation of the debugging session so you can figure out what is happening in the code.

list
Show the lines in the file you are currently debugging. Very helpful if you've drilled down further into the codebase and are unfamiliar with the code.
next
Execute the next line in the file. This allows you to go line by line and inspect the state of the code at that point.
step
Dig deeper into the code that is being called on that line. If it is a function, it will take you into that function so you can inspect the state from there.
continue
Exit out of the debugger but still execute the code. When you do this, it will be like you never stopped the execution of the program in the first place.

Invoking pdb

The easiest way to invoke pdb is to add a set_trace in your code. Here is an example:

import pdb; pdb.set_trace()

This is a PEP8 violation, but you should never check this code in, so we won't worry about that.

Another way is to invoke the pdb module from the command line.

$ python -m pdb mycode.py

Choose the method that works best for your situation. We will use the command line method to see how pdb works in the next section.

Example Debug Session

Here is an example of a debugging session with pdb:

$ python -m pdb example.py
> example.py(1)<module>()
-> my_string = 'one'
(Pdb) next
  1  -> my_string = 'one'
  2     my_other_string = 2
  3
  4     print my_string + my_other_string
> example.py(2)<module>()
-> my_other_string = 2
(Pdb) next
(Pdb) next
  1     my_string = 'one'
  2     my_other_string = 2
  3
  4  -> print my_string + my_other_string
TypeError: "cannot concatenate 'str' and 'int' objects"

Now we are stopped at the line that has the error on it and can inspect the current state of things further.

> example.py(4)<module>()
-> print my_string + my_other_string
(Pdb) type(my_string)
<type 'str'>
(Pdb) type(my_other_string)
<type 'int'>
(Pdb) my_other_string
2

Now, what if I try some alternatives?

(Pdb) print my_string + '2'
one2
(Pdb) print my_string + str(my_other_string)
one2
(Pdb) print '{}{}'.format(my_string, my_other_string)
one2

This gives you a chance to find out what will actually work when you are in this situation. Then you can go modify your code, run your tests and get that bug fixed!

Alternative pdb implementations

There are a few different implementations out there that build upon pdb. These replacements typically enhance the experience by adding things like tab completion and syntax highlighting. My favorite is pdb++ because it has a sticky_by_default option that shows the whole context of the code as you step through it, eliminating the need to use the list command in most cases.

Another alternative is ipdb, which embeds an IPython interpreter as the pdb prompt. If you've ever used IPython, then you know how powerful it can be. Now you can have that power in the debugger.

One main difference between these two alternatives is that ipdb uses a separate import to do a set_trace in the code. Whereas pdb++ overrides the standard set_trace to invoke itself. This makes dropping in pdb++ into your project a seamless operation.

Helpful Links

  • I gave a talk entitled So You Think You Can PDB? at PyOhio 2014, which goes over the basic usage in more detail.
  • Nathan Yergler gave an excellent talk at PyCon 2014, going over a lot more features of pdb and the recent changes in Python 3. Watch In Depth PDB to learn more.

Was this article useful? Let us know in the comments and be sure to sign up for our Plone & Python How-To digests to receive more how-to guides as soon as they are published!

Related Posts
How can we assist you?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.