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》
