Professor Norm Matloff
University of California, Davis
(author of
The Art of Debugging, NSP, 2008
)
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 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.
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.
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, inif __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.