Introduction to the PDB Python Debugging Tool

Professor Norm Matloff
University of California, Davis
(author of The Art of Debugging, NSP, 2008 )

Contents:

Overview:

PDB is Python's built-in debugging tool. While it is not very sophisticated (see WinPDB and Emacs for nice programs), it does the job, and is certainly fine for debugging small programs.

Nothing to install--it comes with Python.

The Principle of Confirmation:

The way that a debugging tool helps you find your bugs is that it makes it easy to apply what I call the Principle of Confirmation:

Keep confirming that what you are "sure" is true, really is true. Eventually you'll find something that doesn't confirm, and then you'll probably have pinpointing the location of a bug.

Are you "sure" that your variable w has the value 88 on line 20? Confirm it! Are you "sure" that in a certain if/else statement, the code takes the else branch in a certain situation? Confirm it! A debugging tool makes this easy to do, by allowing you to execute your program line by line, querying the values of variables along the way.

Example program:

Here is code to do binary search: One has an array (Python list) that is always in sorted order, small to large. We wish to insert a new value, and the code is suppose to tell us the index at which to insert it.

For example, say we wish to insert 6 into [5,12,13]. Then the insertion point would be 1, since the 6 would go just before 12, which has index 1 in the list. The insertion point for 1 would be 0, since 1 would go before the 5.

Here is the buggy code:

def findinspt(x,xnew):  # returns insertion point of xnew in x
   n = len(x)
   lo = 0
   hi = n-1
   while True:
      mid = (lo + hi) / 2
      if xnew > x[mid]: lo = mid + 1
      else: hi = mid
      if xnew == x[mid]: return mid

def main():
   y = [5,12,13]
   print findinspt(y,3)

if __name__ == '__main__': main()

Don't worry about that last line for now; just make sure to include it, and make sure to have a function named main() at which execution is to begin.

Sample debugging session:

Let's try running the program, which I named bsrch.py. I opened a terminal window, and did the following (this was on Linux, but would be the same elsewhere:

% python bsrch.py
Traceback (most recent call last):
  File "bsrch.py", line 16, in 
    if __name__ == '__main__': main()
  File "bsrch.py", line 14, in main
    print findinspt(y,3)
  File "bsrch.py", line 8, in findinspt
    if xnew > x[mid]: lo = mid + 1
KeyboardInterrupt

The program went into an apparent infinite loop, so I killed it using ctrl-c. I then reran it under PDB:

python -m pdb bsrch.py 
> /home/nm/145/bsrch.py(2)()
-> def findinspt(x,xnew):  # returns insertion point of xnew in x
(Pdb) l
  1     
  2  -> def findinspt(x,xnew):  # returns insertion point of xnew in x
  3        n = len(x)
  4        lo = 0
  5        hi = n-1                  
  6        while True:
  7           mid = (lo + hi) / 2
  8           if xnew > x[mid]: lo = mid + 1
  9           else: hi = mid
 10           if xnew == x[mid]: return mid
 11     

PDB gave me its (pdb) prompt, and to take a look around, I gave the l (list code) command. PDB responded by showing me a few lines of code. I could have hit l again to see more, and just hit the Enter key (which repeats the last command).

I decided to see a breakpoint at line 7, which tells PDB to pause execution of the program whenever it hits that line. I then hit c (continue) to resume execution, and sure enough, PDB paused there:

(Pdb) b 7
Breakpoint 1 at /home/nm/145/bsrch.py:7
(Pdb) c
> /home/nm/145/bsrch.py(7)findinspt()
-> mid = (lo + hi) / 2

I could then "take a look around," querying the values of variables:

(Pdb) lo
0
(Pdb) hi
2
(Pdb) x
[5, 12, 13]
(Pdb) print n
3

Note that I could not just type n to display that variable, since n is a PDB command to go to the next line.