ipdb, the iPython debugger
Introduction¶
Python comes with a very useful debugger called pdb
. The iPython project provides an enhanced version of pdb
called ipdb
. The ipdb
debugger provides the same standard debugging commands as pdb
, and it includes some nice additional features such as tab completion.
Installation¶
Install ipdb
from the Python Package Index.
pip install ipdb
On Windows, you have to install the pyreadline
library as well
pip install pyreadline
Basic debugging¶
Let’s step through a very simple Python program. Add this to a file called example.py
def main():
"""
Main function
"""
x = 34
y = 3
z = y/x
print(x,y,z)
if __name__ == '__main__':
main()
Run it, wrapped in the ipdb
debugger.
ipdb example.py
If you are using Python 3, the debugger script is called ipdb3
instead of ipdb
ipdb3 example.py
The debugger starts up, and waits at the first line.
> /home/example.py(1)<module>()
----> 1 def main():
2 """
3 Main function
First, let’s get help on what commands are available. Type ?
and press enter.
ipdb> ?
Documented commands (type help <topic>):
========================================
EOF bt cont enable jump pdef psource run unt
a c continue exit l pdoc q s until
alias cl d h list pfile quit step up
args clear debug help n pinfo r tbreak w
b commands disable ignore next pinfo2 restart u whatis
break condition down j p pp return unalias where
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
retval rv
More help is available for each command.
ipdb> ?s
s(tep)
Execute the current line, stop at the first possible occasion
(either in a function that is called or in the current function).
Basic usage¶
Step through the program with s
until you get past the line where 34 is assigned to x
.
Now that we’re here, let’s see what value x
holds. Type x
and ipdb
will display the value of x
.
Set a breakpoint
ipdb> b 8
Breakpoint 1 at /home/example.py:8
Use c
to continue execution until that breakpoint.
Use q
to quit out of the debugger.
iPython additions¶
ipdb
adds some useful features above what plain pdb
provides. The most useful is tab-completion. Any identifiers that are defined in locals() or in globals() can be tab-completed.
The “magic” commands (%
, ??
) from the regular iPython shell are not available in ipdb
. Instead, ipdb
provides some extra debugger commands, prefixed with a “p”. pinfo obj
is the same as obj?
in the iPython shell.
Step in to example.py
, past the definition of main()
. Type pinfo main
ipdb> pinfo main
Signature: main()
Docstring: Main function
File: ~/example.py
Type: function
This shows us some useful information about the main()
function.
psource
will display the source of an object.
ipdb> psource main
def main():
"""
Main function
"""
x = 34
y = 3
z = y/x
print(x,y,z)
Further reading¶
We have just scratched the surface of pdb
and ipdb
. There is good information available right in the debugger,
available by typing ?pdb
.
For more information about plain pdb
and its commands, the “Python Module of the Week” series did a nice introduction.
Alternatives¶
The pudb
debugger presents a more visual display, with separate panes for breakpoints and local variables. It is available on Linux and OS X.
For more intractable problems, the Linux strace
utility traces all system calls made by a program. It can attach to an already-running process, and can capture all the file and network input and output.
strace -o output.txt python example.py
grep example output.txt
This shows us all the occurrences of the word ‘example’ in the system calls that happen when we run python example.py
execve("/home/.virtualenvs/test/bin/python", ["python", "example.py"], [/* 36 vars */]) = 0
readlink("example.py", 0x7ffe244a2fe0, 4096) = -1 EINVAL (Invalid argument)
lstat("/home/example.py", {st_mode=S_IFREG|0664, st_size=135, ...}) = 0
stat("example.py", {st_mode=S_IFREG|0664, st_size=135, ...}) = 0
open("example.py", O_RDONLY) = 3
stat("example.py", {st_mode=S_IFREG|0664, st_size=135, ...}) = 0
open("example.py", O_RDONLY) = 3
Let’s remove read permissions for example.py
chmod a-r example.py
If we run our strace
again, we see that the open
syscall now returns an error.
execve("/home/virtualenvs/test/bin/python", ["python", "example.py"], [/* 36 vars */]) = 0
readlink("example.py", 0x7ffc15852b60, 4096) = -1 EINVAL (Invalid argument)
lstat("/home/example.py", {st_mode=S_IFREG|0220, st_size=135, ...}) = 0
stat("example.py", {st_mode=S_IFREG|0220, st_size=135, ...}) = 0
open("example.py", O_RDONLY) = -1 EACCES (Permission denied)
stat("example.py", {st_mode=S_IFREG|0220, st_size=135, ...}) = 0
open("example.py", O_RDONLY) = -1 EACCES (Permission denied)
write(2, "python: can't open file 'example"..., 67) = 67
Chad Fowler and Julia Evans have written good introductions to strace
.