用IPython进行调试,有些事情没人愿意做,调试便是其中之一。但是,掌握调试技术还是非常有必要的。调试可能要耗费数小时时间,而且根据墨菲定律(Murphy’s law),你真正能留给调试的时间很可能会很少。因此,你要熟悉自己所用的调试工具,做相关的事情时要有计划、有条理。当你找到并修复一个bug后,应该立即做一个测试,这样至少能避免在相同的地方再经历一次痛苦的调试过程。我们将调试下面这段有bug的代码,其中的一条语句试图访问一个不存在的数组元素。
import numpy
a = numpy.arange(7)
print a[8]
IPython调试器的功能和标准的Python pdb调试器类似,但增加了TAB键代码补全和语法突出显示等特性。
具体步骤
下面的步骤展示了一个典型的调试过程。
- 在IPython中运行有bug的脚本。
开启一个IPython shell。用如下命令在IPython中运行有bug的脚本。
In [1]: %run buggy.py
------------------------------------------------------------------
IndexError Traceback (most recent call last)
.../site-packages/IPython/utils/py3compat.pyc in execfile(fname,*where)
173 else:
174 filename = fname
--> 175 __builtin__.execfile(filename, *where)
.../buggy.py in ()
2
3 a = numpy.arange(7)
----> 4 print a[8]
IndexError: index out of bounds
- 启动调试器。
既然程序已经崩溃,我们可以启动调试器了。错误所在的行会被自动设置一个断点。
In [2]: %debug
> .../buggy.py(4)()
2
3 a = numpy.arange(7)
----> 4 print a[8]
- 列出代码。
可以使用list
(或l
)命令列出代码。
ipdb> list
1 import numpy
2
3 a = numpy.arange(7)
----> 4 print a[8]
- 在当前行评估代码。
我们可以在当前行(即调试器当前指向的行)评估或执行任意的代码。
ipdb> len(a)
7
ipdb> print a
[0 1 2 3 4 5 6]
- 查看调用栈。
调用栈包含了正在运行的程序中处于活动状态的函数的信息。可以使用bt
命令查看调用栈。
ipdb> bt
.../py3compat.py(175)execfile()
171 if isinstance(fname, unicode):
172 filename = fname.encode(sys.getfilesystemencoding())
173 else:
174 filename = fname
--> 175 __builtin__.execfile(filename, *where)
> .../buggy.py(4)()
0 print a[8]
在调用栈中返回到上一级。
ipdb> u
> .../site-packages/IPython/utils/py3compat.py(175)execfile()
173 else:
174 filename = fname
--> 175 __builtin__.execfile(filename, *where)
在调用栈中进入到下一级。
ipdb> d
> .../buggy.py(4)()
2
3 a = numpy.arange(7)
----> 4 print a[8]
攻略小结
本章介绍了怎样使用IPython调试一个NumPy程序。我们设置了一个断点,并且能定位到调用栈中的适当位置。本章用到了下列调试命令。
命令 | 功能描述 |
---|---|
list或l | 列出源代码 |
bt |
显示调用栈 |
u |
在调用栈中返回到上一级 |
d |
在调用栈中进入到下一级 |