茶亦醉人何必酒,书能香我无须花!

张帆风顺破重浪,兰幽山间心坦荡。 斌礼厚徳创伟业,志壮凌云走四方!
posts - 170, comments - 560, trackbacks - 8, articles - 4
  博客园 :: 首页 ::  :: 联系 :: 订阅 订阅 :: 管理

公告

[Dynamic Language] Python Debugger pdb

Posted on 2010-10-11 17:56 ※ABeen※ 阅读(78) 评论(0) 编辑 收藏

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():
test2(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
9 print x
10
11 def 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 16 2010, 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
4 def testB(i):
5 -> a = "abeen"
6 b = 1024
7 x = b / i
8 x += 1
9 print x
10
11 def 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
9 print 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
4 def testB(i):
5 a = "abeen"
6 b = 1024
7 -> x = b / i
8 x += 1
9 print x
10
11 def 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
9 print 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》