ipdb 使用小记

最近在魔改 loss function,涉及到很多矩阵运算,而矩阵运算中维度的对齐免不了要多次的调试;沿袭着之前的 print 大法弄了一段时间后,不仅代码凌乱不堪,而且心累:每次 import tensorflow as tf 都要十几秒,然后 print 完之后想进一步看其他变量的信息,又要重新执行一遍。后来找到了 ipdb 这个好用的工具,才发现自己过去调试程序的方法是多么的低效和 naive。

python 提供了一个默认的 debugger:pdb,而 ipdb 则是 pdb 的增强版,提供了补全、语法高亮等功能,类似于 ipython 与 python 默认的交互终端的关系,通过 pip install ipdb 即可安装 ipdb。

使用方式

ipdb 的使用方法一般有两种:集成到源代码或通过命令交互

集成到源代码可以直接在代码指定位置插入断点。如下所示:

1
2
3
4
import ipdb
var1 = 23
ipdb.set_trace()
...

上面的代码会在执行完 var1 = 23 这条语句之后停止,展开 ipython 环境,之后就可以自由地调试了。

上面的方式虽然简单,但是存在着两个较为比较明显的问题:

  1. 插入的断点代码会污染原来的代码空间
  2. 每次插入断点都需要修改源码

因此,相比于上面的方式,交互式的命令式调试方法更加方便。启动命令式调试环境的方法也很简单:

python -m ipdb code.py

接着就是通过一些常用的命令来进行 debug 了,如上面插入断点的样例代码就可以通过以下命令达到同样效果:

1
2
3
4
$python -m ipdb code.py
ipdb> b 3
Breakpoint 1 at /test.py:3
ipdb> c

上面的命令 b 3 表示在第三行设置一个断点,然后通过命令 c 一直执行至断点处,接着就会展开 ipython 环境进行调试了。(bc 分别代表了 break 和 continue,可以用整条命令,也可以只用首字母)

常用命令

上面的设置断点和一直执行至断点是比较常见的用法,除此之外,还有其他一些常用命令。

帮助

通过命令 h 可以列出所有命令,后面跟上具体的命令如 h command 则可以显示出这条命令的具体作用,非常有用,依靠这条命令能够节省不少 google 的次数。

断点

上面提到了断点的一种常见用法,即命令 b line_numberc 的组合,b line_number 默认是对当前文件设置断点,也可以在 line_number 前加上其他文件名(比如说要将要引用的其他文件),即 b file_name:line_number;file_name 需要在 sys.path 中,当前目录已经默认存在 sys.path , 也可通过 .. 引用上一层目录的文件。

另外,通过 b 设置的断点在重新运行 debug 程序 (命令 restartrun) 后会依然保留,如果要忽略这些断点,有两种做法

  1. 通过 disable 关闭这些断点,enable 打开这些断点
  2. 通过命令 clearcl 清除这些断点

此外,除了上面那种一直存在的断点,ipdb 中还有一种 只生效一次的断点,命令为 tbreak, 使用方法同命令 b

上面的断点都是直接指定的,pdb 中还有一种条件断点,即只有当某个条件成立时,才设置断点,其使用命令为 condition line_num bool_expression, condition 为关键字,line_num 为设定断点的位置,只有当 expression 为 true 时, 才会设置这个断点。

如果需要列出已经设置的所有断点,可以单独使用命令 b

逐行执行

有两条命令可以进行逐行执行: s(step) 或 n(next), 两个命令的主要区别是:假如当前行调用了某个函数,s 会进入这个函数,n 则不会。因此,如果需要了解函数内部执行的细节,需要 s 命令进入函数内部进行 debug。

进入了函数之后,通过命令 a(argument) 可列出当前的函数的参数,通过 r(return)则可以直接执行至 return 语句。

忽略某段代码

使用 j line_number 可以忽略某段代码,下一步直接从 line_number 开始执行。

查看源码

通过命令 lll 可查看源码, ll 是查看整个源码文件, l 可指定需要查看的行数,默认是当前往后 11 行,也可指定具体的范围,如 l 2,5 是查看第 2-5 行的源码。

重启或退出 debugger

上面已经提到了重启 debugger 可通过 restartrun 命令,需要注意的是,重启 debugger 后断点、debugger 的设置等是会保留的。如果要一个全新的 debugger,可通过命令 qquitexit 退出 debugger 后进入。

小结

以上就是 ipdb 的一些基本用法,除此之外,更多的用法可参考 pdb 的官方文档,ipdb 的命令跟 pdb 是一样的。另外,gdb 也是一个类似的命令行 debugger,只是一般用来调试 C/C++ 而已,使用的方法类似,甚至很多命令的名称更 pdb 都一样,具体可参考 用 GDB 调试程序