Home Page

Breakpoint-induced Python debugging with IPython

Wednesday, June 25th, 2008

Most of the Python programmers out there will know about IPython. Most of them will also know about the Python Debugger (PDB).

IPython has an advanced version of PDB (spectacularly named 'ipdb') which does the same for PDB as IPython does for the normal interactive Python interpreter. It adds tab completion, color syntax highlighting, etc. The -pdb switch to IPython gives us access to the debugger automatically in the event of uncaught exceptions:

def ham():
	x = 5
	raise NotImplementedError('Use the source, luke!')
 
ham()

We now run this code using ipython -pdb

[todsah@jib]~$ ipython -pdb 
In [1]: import test.py
<type 'exceptions.NotImplementedError'>: Use the source, luke!
> /home/todsah/test.py(5)ham()
      4         x = 5
----> 5         raise NotImplementedError('Use the source, luke!')
      6 

ipdb> print x
5

And as you can see we get dropped at a nice ipdb> prompt which allows us to use the additional power of IPython to investigate the problem.

Like most decent debuggers, we can also use PDB to set breakpoints. In Python, we do that in the code, rather than via external means. To do this, we import the pdb module and tell it to drop us into the debugger when execution hits the pdb.set_trace() line.

import pdb
def ham():
	x = 5
	pdb.set_trace()
 
ham()

We run it, and lo and behold, we get dropped into the pdb debugger:

In [1]: import test.py
> /home/todsah/test.py(8)ham()
-> raise NotImplementedError('Use the source, luke!')
(Pdb) print x
5

Buuuuut… as you can see from the (Pdb) prompt, this is the normal PDB debugger, not IPython's enhanced version. Wouldn't it be neat to be able to use IPython's debugger for breakpoint-induced debugging too? I spent some time looking around on the Interwebz, trying to find out how to do this, and to my surprise I couldn't find anything? So I dove into the IPython source and discovered IPython.Debugger.Tracer:

from IPython.Debugger import Tracer; debug_here = Tracer()
 
def ham():
	x = 5
	debug_here()
	raise NotImplementedError('Use the source, luke!')
 
ham()

Now when we execute this code, we're dropped into the IPython enhanced IPDB debugger:

In [1]: import test 
> /home/todsah/test.py(8)ham()
      7         debug_here()
----> 8         raise NotImplementedError('Use the source, luke!')
      9 

ipdb> print x
5

We can use tab completion and all the other goodies IPython offers over standard Python now.