[Dynamic Language] Python Debugger pdb

Python pdb 和 GNU gdb 一样容易上手,Module pdb 本身就包含了调式工具。

abeen@localhost:~/learn_test/pdb$ cat test.py
#!/usr/bin/env python
#
_*_ coding:utf-8 _*_

def testB(i):
a
="abeen"
b
=1024
x
= b / i
x
+=1
print x

def testA():
testB(0)

def main():
testA()

if__name__=="__main__":
main()

运行调试

abeen@localhost:~/learn_test/pdb$ pdb test.py //启动调试
>/home/abeen/learn_test/pdb/test.py(4)<module>()
->def testB(i):
(Pdb) l
//显示代码
1#!/usr/bin/env python
2# _*_ coding:utf-8 _*_
3
4->def testB(i):
5 a ="abeen"
6 b =1024
7 x = b / i
8 x +=1
9print x
10
11def testA():
(Pdb) b
7//设置断点
Breakpoint
1 at /home/abeen/learn_test/pdb/test.py:7
(Pdb) b
8//设置断点
Breakpoint
2 at /home/abeen/learn_test/pdb/test.py:8
(Pdb) b
//查看断点
Num Type Disp Enb Where
1 breakpoint keep yes at /home/abeen/learn_test/pdb/test.py:7
2 breakpoint keep yes at /home/abeen/learn_test/pdb/test.py:8
(Pdb) c
>/home/abeen/learn_test/pdb/test.py(7)testB()
-> x = b / i
(Pdb) p a,b,i
(
'abeen', 1024, 0)
(Pdb) w
//查看调用
/usr/lib/python2.6/bdb.py(368)run()
->exec cmd in globals, locals
<string>(1)<module>()
/home/abeen/learn_test/pdb/test.py(18)<module>()
-> main()
/home/abeen/learn_test/pdb/test.py(15)main()
-> testA()
/home/abeen/learn_test/pdb/test.py(12)testA()
-> testB(0)
>/home/abeen/learn_test/pdb/test.py(7)testB()
-> x = b / i

也可以在源代码中直接导入 pdb Module 进行调试。pdb.set_trace() 会启动 pdb 调试状态,可以是源代码的任何位置。

abeen@localhost:~/learn_test/pdb$ cat test.py
#!/usr/bin/env python
#
_*_ coding:utf-8 _*_

def testB(i):
a
="abeen"
b
=1024
x
= b / i
x
+=1
print x

def testA():
testB(0)

def main():
testA()

if__name__=="__main__":
import pdb
pdb.set_trace()
main()

pdb Module 中还提供了一些实用的函数,便于我们在 Python/iPython 交互模式下进行调试。

abeen@localhost:~/learn_test/pdb$ ipython
Python
2.6.5 (r265:79063, Apr 162010, 13:57:41)
In [
1]: from test import*
In [
2]: pycat te
test.py test.pyc testA testB
In [
2]: pycat test
#!/usr/bin/env python
#
_*_ coding:utf-8 _*_

def testB(i):
a
="abeen"
b
=1024
x
= b / i
x
+=1
print x

def testA():
testB(0)

def main():
testA()

if__name__=="__main__":
main()

In [
3]: import pdb
In [
5]: pdb.runcall(testB, 1)
>/home/abeen/learn_test/pdb/test.py(5)testB()
-> a ="abeen"
(Pdb) l
1#!/usr/bin/env python
2# _*_ coding:utf-8 _*_
3
4def testB(i):
5-> a ="abeen"
6 b =1024
7 x = b / i
8 x +=1
9print x
10
11def testA():
(Pdb) b
5
Breakpoint
1 at /home/abeen/learn_test/pdb/test.py:5
(Pdb) b
7
Breakpoint
2 at /home/abeen/learn_test/pdb/test.py:7
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at /home/abeen/learn_test/pdb/test.py:5
2 breakpoint keep yes at /home/abeen/learn_test/pdb/test.py:7 

另外一个需要关注的函数是 pdb.pm(),一旦程序出错发生未处理异常,它可以带我们去 "死亡现场" 查勘一番,类似 gdb core 或者 windbg dump。

In [10]: pfile testB
def testB(i):
a
="abeen"
b
=1024
x
= b / i
x
+=1
print x

def testA():
testB(0)

def main():
testA()

if__name__=="__main__":
main()

In [
11]: testB(0)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)

/home/abeen/learn_test/pdb/<ipython console>in<module>()

/home/abeen/learn_test/pdb/test.py in testB(i)
5 a ="abeen"
6 b =1024
---->7 x = b / i
8 x +=1
9print x

ZeroDivisionError: integer division
or modulo by zero

In [
12]: pdb.pm()
>/home/abeen/learn_test/pdb/test.py(7)testB()
-> x = b / i
(Pdb) w
/usr/lib/pymodules/python2.6/IPython/iplib.py(2257)runcode()
->exec code_obj in self.user_global_ns, self.user_ns
<ipython console>(1)<module>()
>/home/abeen/learn_test/pdb/test.py(7)testB()
-> x = b / i
(Pdb) l
2# _*_ coding:utf-8 _*_
3
4def testB(i):
5 a ="abeen"
6 b =1024
7-> x = b / i
8 x +=1
9print x
10
11def testA():
12 testB(0)
(Pdb) p a,b,i
(
'abeen', 1024, 0)
(Pdb)

pdb.pm() 实际调用的是 pdb.post_mortem() 函数,并将 sys.last_traceback 作为调用参数。其实在 iPython 里面我们直接设置 "%pdb ON" 就可以了,并不需要手工调用 pdb.pm()。

In [15]: %pdb 1
Automatic pdb calling has been turned ON

In [
16]: testB(0)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)

/home/abeen/learn_test/pdb/<ipython console>in<module>()

/home/abeen/learn_test/pdb/test.py in testB(i)
5 a ="abeen"
6 b =1024
---->7 x = b / i
8 x +=1
9print x

ZeroDivisionError: integer division
or modulo by zero
>/home/abeen/learn_test/pdb/test.py(7)testB()
6 b =1024
---->7 x = b / i
8 x +=1

 

 

---------------------------------------------------

更多细节可参考:

 官方文档: 《26.2. pdb — The Python Debugger》
Python Conquers The Universe: 《Debugging in Python》
Jeremy Jones: 《Interactive Debugging in Python》

posted @ 2010-10-11 17:56  ABeen  阅读(398)  评论(0编辑  收藏  举报