Python DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


Interactive Debugging in Python
Pages: 1, 2, 3, 4, 5, 6, 7

My next trick is to set a break point in f4() using the (b)reak command, and continue to the break point using the (c)ontinue command:



(Pdb) b f4
Breakpoint 1 at /home/jmjones/svn/articles/debugger
  /simple_debugger_example.py:22
(Pdb) c
2
3
> /home/jmjones/svn/articles/debugger/simple_debugger_example.py(23)f4()
-> print some_arg
(Pdb) l
 18         print some_arg
 19         some_other_arg = some_arg + 1
 20         return f4(some_other_arg)
 21
 22 B   def f4(some_arg):
 23  ->     print some_arg
 24         some_other_arg = some_arg + 1
 25         return some_other_arg
 26
 27     if __name__ == "__main__":
 28         pdb.runcall(f1, 1)
(Pdb)

The break command creates break points that the debugger will stop at when it encounters them. The continue command tells the debugger to keep executing code until it hits a break point or EOF.

I next issued a (w)here command:

(Pdb) where
  /usr/local/python24/lib/python2.4/bdb.py(404)runcall()
-> res = func(*args, **kwds)
  /home/jmjones/svn/articles/debugger/simple_debugger_example.py(10)f1()
-> return f2(some_other_arg)
  /home/jmjones/svn/articles/debugger/simple_debugger_example.py(15)f2()
-> return f3(some_other_arg)
  /home/jmjones/svn/articles/debugger/simple_debugger_example.py(20)f3()
-> return f4(some_other_arg)
> /home/jmjones/svn/articles/debugger/simple_debugger_example.py(23)f4()
-> print some_arg
(Pdb)

The where command prints out a stack trace, showing the call tree from f1() to f4(). This can help you see how a function is being called.

I then navigated up the stack trace with the (u)p command and saw where I was with the list command:

(Pdb) u
> /home/jmjones/debugger/simple_debugger_example.py(20)f3()
-> return f4(some_other_arg)
(Pdb) u
> /home/jmjones/debugger/simple_debugger_example.py(15)f2()
-> return f3(some_other_arg)
(Pdb) u
> /home/jmjones/debugger/simple_debugger_example.py(10)f1()
-> return f2(some_other_arg)
(Pdb) u
> /usr/local/python24/lib/python2.4/bdb.py(404)runcall()
-> res = func(*args, **kwds)
(Pdb) u
*** Oldest frame
(Pdb) l
399             self.reset()
400             sys.settrace(self.trace_dispatch)
401             res = None
402             try:
403                 try:
404  ->                 res = func(*args, **kwds)
405                 except BdbQuit:
406                     pass
407             finally:
408                 self.quitting = 1
409                 sys.settrace(None)
(Pdb)

The up command moves the debugger up a frame in the stack trace to an older frame. In this example, it took me all the way up to the oldest frame, which is one of the debugger modules, bdb.py. This is because the debugger (part of which is in bdb.py) is actually executing this example script.

I navigated down the stack trace a few frames with the (d)own command, which is the opposite of the up command:

(Pdb) d
> /home/jmjones/svn/articles/debugger/simple_debugger_example.py(10)f1()
-> return f2(some_other_arg)
(Pdb) d
> /home/jmjones/svn/articles/debugger/simple_debugger_example.py(15)f2()
-> return f3(some_other_arg)
(Pdb) l
 10         return f2(some_other_arg)
 11
 12     def f2(some_arg):
 13         print some_arg
 14         some_other_arg = some_arg + 1
 15  ->     return f3(some_other_arg)
 16
 17     def f3(some_arg):
 18         print some_arg
 19         some_other_arg = some_arg + 1
 20         return f4(some_other_arg)
(Pdb)

I moved down two frames into f2(), but what does it really mean to be in a different frame? As an illustration, I've printed out a couple of variables in two different frames:

(Pdb) print some_arg
2
(Pdb) d
> /home/jmjones/svn/articles/debugger/simple_debugger_example.py(20)f3()
-> return f4(some_other_arg)
(Pdb) l
 15         return f3(some_other_arg)
 16
 17     def f3(some_arg):
 18         print some_arg
 19         some_other_arg = some_arg + 1
 20  ->     return f4(some_other_arg)
 21
 22 B   def f4(some_arg):
 23         print some_arg
 24         some_other_arg = some_arg + 1
 25         return some_other_arg
(Pdb) print some_arg
3
(Pdb)

I went from f2() down to f3() and printed out some_arg in both of them. I saw 2 from f2() and 3 from f3(). What would happen if I were to step forward? Back up into f2() to see a clearer illustration:

(Pdb) u
> /home/jmjones/debugger/simple_debugger_example.py(15)f2()
-> return f3(some_other_arg)
(Pdb) l
 10         return f2(some_other_arg)
 11
 12     def f2(some_arg):
 13         print some_arg
 14         some_other_arg = some_arg + 1
 15  ->     return f3(some_other_arg)
 16
 17     def f3(some_arg):
 18         print some_arg
 19         some_other_arg = some_arg + 1
 20         return f4(some_other_arg)
(Pdb) s
4
> /home/jmjones/debugger/simple_debugger_example.py(24)f4()
-> some_other_arg = some_arg + 1
(Pdb) l
 19         some_other_arg = some_arg + 1
 20         return f4(some_other_arg)
 21
 22 B   def f4(some_arg):
 23         print some_arg
 24  ->     some_other_arg = some_arg + 1
 25         return some_other_arg
 26
 27     if __name__ == "__main__":
 28         pdb.runcall(f1, 1)
[EOF]
(Pdb)

If the debugger really were in f2(), stepping forward should have taken it into f3() if it hadn't yet made the call to f3(), or up into f1() if f3() had already returned. Instead, it jumped to f4(). Navigating up or down a stack trace provides access to that frame's local namespace, but that appears to be about it.

Those are the majority of my most frequently used commands.

Pages: 1, 2, 3, 4, 5, 6, 7

Next Pagearrow





Sponsored by: