Python 调试工具 pudb 的使用指南
最近在调试python程序,对于这种动态语言,我之前的方法大多都是打tag,真是痛苦的要死。话说回来,debug是为了什么?debug可以看成是对我们的猜测的一种验证。如果我们能通过工具将需要的信息(变量、堆栈)都显示出来,调试就很有效率。下面就介绍一个python调试工具:pudb。
本文部分内容参考自Professor Norm Matloff的文章,我特此发了邮件给他征得了翻译的权限。
Professor Norm Matloff, that is very nice of you, and thanks.
pudb是全屏的基于控制台的可视化调试器。如果你还记得Turbo C的话,看到这个你应该会感到亲切的。Homepage
先概要看一下pudb的特性:
- 源码语法高亮,栈、断点、变量可见并且一直动态更新。变量展示还有很多可以定制化的功能。
- 基于键盘,简单高效。为什么说高效呢?因为它支持VI的鼠标移动。还支持PDB的某些命令
- 支持查找源代码,可以使用m代用module browser查看载入的模块
- 断点设置:鼠标移到某行代码,按b,然后可以在断点窗口编辑断点
- PuDB看重异常处理,post-mortem模式使折回到crash的最后一步更简单
安装
Python
1
2
3
|
pip install pudb
or
easy_install pudb
|
使用
为了支持pudb,需要在代码中插入
Python
1
2
3
|
from pudb import set_trace; set_trace()
or
import pudb; pu.db
|
然后通过下面命令启动pudb
Python
1
|
pudb my–script.py
|
step by step
我们以下面这段二分程序binsearch.py为例子
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
import pudb; pu.db
def findinspt(x, xnew):
n = len(x)
lo = 0
hi = n–1
while True:
mid = (lo + hi) / 2
if xnew > x[mid]:
lo = mid + 1
else:
hi = mid
if xnew == x[mid]:
return mid
if __name__ == “__main__”:
y = [5,12,13]
print findinspt(y,3)
print findinspt(y,8)
print findinspt(y,12)
print findinspt(y,30)
|
运行下面命令
Python
1
|
pudb binsearch.py
|
不出意外会得到下面的窗口,左半边是源代码,右边一次是变量窗口、程序调用栈、断点
先介绍几个简单命令,不需要记住,因为下面会多次提到
- n: next,也就是执行一步
- s: step into,进入函数内部
- c: continue
- b: break point,断点
- !: python command line
- ?: help
最重要的是记住?,需要的时候按”?”查询
我们按一下n会发现y=[5,12,13]这行代码高亮显示了,表示执行到了这行代码。
再按一下n,y=[5,12,13]这行代码就执行完了,仔细看会发现右上角的变量窗口出现了y:list,表示程序内存中有了变量y。后面的List是type。
要查看y的值,按s即可。但是如果这个时候你要是不小心按到了Enter,你会发现下面的界面。
对的,这就是有关变量的所有信息。你只需要将光标移动到你要查看的信息,比如 Show repr(),按’Enter’键,再移动向右方向键到ok上,再按Enter键,就可以查看相应的信息的。但是如果你查看了变量不存在的信息,就会出现下面的画面。
当光标停在函数上的时候可以选择n执行到下一行代码,或者s进入函数内部。正常如果有终端输出的时候,pudb会回到终端。但是我在mac上并没有回去,有待进一步验证。这个时候我们执行n的时候,如果函数有问题,会出现异常:[PROCESSING EXCEPTION – hit e to examine]。按e就会显示异常的具体信息。
下面就是进入函数进行调试了。先按q选择restart重启pudb,执行到上面异常的哪一行选择s进入函数内部。这个时候findinspet()函数内部的变量就会显示在右上角变量窗口中。按n单步调试一会,发现lo,hi都变成0了。说明出现问题了。
修改程序。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
import pudb; pu.db
def findinspt(x, xnew):
n = len(x)
lo = 0
hi = n–1
while True:
mid = (lo + hi) / 2
if xnew > x[mid]:
lo = mid + 1
else:
hi = mid
if xnew == x[mid]:
return mid
if lo == hi:
return lo
if __name__ == “__main__”:
y = [5,12,13]
print findinspt(y,3)
print findinspt(y,8)
print findinspt(y,12)
print findinspt(y,30)
|
重新启动pudb。光标到main,按c会得到如下界面。
这时候选择restart,然后按o就可以看到输出结果了。
结果对于3,8,12都是对的,30的插入位置不对。为了让debug效率更高,下面使用断点功能。使用向下方向键,光标移动到第13行,按b即在该行设置了断点,右下角的断点显示窗口可以看到。
但是我们只想debug当xnew等于30的时候的情况。先使用向右方向键,再使用向下方向键到断点显示窗口的断点上,按Enter。下图。在condition的右侧设置条件xnew==30,点击OK保存。
使用方向键切换到左侧源码部分,先按n单步执行到main主程序,然后按c,程序就执行到了断点位置处。从右侧可以看到xnew的值为30。
这个时候就可以根据我们需要来单步调试了。对于本文的程序,会发现需要对边界条件处理一下。程序改为下面即可。
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import pudb; pu.db
def findinspt(x, xnew):
n = len(x)
lo = 0
hi = n–1
while True:
mid = (lo + hi) / 2
if xnew > x[mid]:
lo = mid + 1
else:
hi = mid
if xnew == x[mid]:
return mid
if lo == hi:
if xnew <= x[lo]:
return lo
else:
return lo
if __name__ == “__main__”:
y = [5,12,13]
print findinspt(y,3)
print findinspt(y,8)
print findinspt(y,12)
print findinspt(y,30)
|
到此,基本上涉及了Debug的一些主要情况。如果说最后的程序是一个产品,Debug就是产品出问题时候的用来解决问题的工具。使用工具的效率一定程度也决定了产品的生产效率。
打赏支持我写出更多好文章,谢谢!
打赏作者
打赏支持我写出更多好文章,谢谢!
任选一种支付方式
转载自演道,想查看更及时的互联网产品技术热点文章请点击http://go2live.cn