[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()
#!/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
>/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()
#!/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
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)
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
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》