目录
pdb
pdb 是 Python 自带的程序包,为 Python 程序提供了一种可交互的源码调试功能。主要特性包括:
- 设置断点
- 单步调试
- 进入函数调试
- 查看当前代码
- 查看栈片段
- 动态修改变量值
pdb 的 Debug 方式
- pdb 可以在源码内直接使用,相当于打断点,
import pdb
后,在需要调试的代码处添加写入pdb.set_trace()
语句即可。
def pushit():
import pdb
pdb.set_trace()
stack.append(raw_input('Enter New String: ').strip())
- 通过命令行参数的形式来进行调试,EG.
python -m pdb stack_demo.py
- 在 Python 交互环境中调试
>>> import pdb
>>> import mymodule
>>> pdb.run(‘mymodule.test()’)
pdb 的调试指令
指令 | 解析 |
---|---|
break [codeline] 或 b [codeline] | 在 codeline 行处,设置断点 |
condition codeline [condition] | 设置条件断点 |
disable [codeline] | 使某一行断点失效 |
enable [codeline] | 使某一行的断点生效 |
clear [codeline] 或 cl [codeline] | 就是清除指定的断点,不带参数就是清除所有的断点 |
continue 或 c | 继续执行程序 |
list 或 l | 查看当前行上下文的代码段 |
next 或 n | 执行下一行,但跳过函数 |
step 或 s | 执行下一行,并进入被调用的函数 |
j [codeline] | 跳转到前面的 codeline 行 |
w | 打印当前执行点的位置 |
return 或 r | 执行代码直到从当前函数返回 |
p | 打印一个变量或参数的值 |
a | 打印当前函数及参数的值 |
! | 感叹号后面跟着语句,可以直接改变某个变量值 |
exit 或 q | 中止并退出 |
help [command] 或 h [command] | commands 的帮助手册 |
示例
stack_demo.py : 一个 Python 实现的 栈 数据结构
stack = []
def pushit():
#import pdb
#pdb.set_trace()
stack.append(raw_input('Enter New String: ').strip())
def popit():
if len(stack) == 0:
print "Cannot pop from an empty stack!"
else:
print 'Remove [', `stack.pop()`, ']'
def viewstack():
print stack
CMDs = {'u':pushit, 'o':popit, 'v':viewstack}
def showmenu():
pr = """
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: """
while True:
while True:
try:
choice = raw_input(pr).strip()[0].lower()
except (EOFError, KeyboardInterrupt, IndexError):
choice = 'q'
print '\nYou picked: [%s]' % choice
if choice not in 'uovq':
print 'Invalid option, try again'
else:
break
if choice == 'q':
break
CMDs[choice]()
if __name__ == '__main__':
showmenu()
通过命令行参数的形式来进行调试
In [2]: !python -m pdb stack_demo.py
> d:\development\python27\workspace\stack_demo.py(1)<module>()
-> stack = [] # 这种方式会从第一条语句开始进入调试
(Pdb) b 7 # 空白行或注释不能打断点
*** Blank or comment
(Pdb) b 8 # 在 codeline == 8 处打上断点
Breakpoint 1 at d:\development\python27\workspace\stack_demo.py:8
(Pdb) n # 下一行
> d:\development\python27\workspace\stack_demo.py(3)<module>()
-> def pushit():
(Pdb) n # 下一行,并且跳过函数内的语句
> d:\development\python27\workspace\stack_demo.py(10)<module>()
-> def popit():
(Pdb) l # 列出下面的代码
3 def pushit():
4
5 #import pdb
6 #pdb.set_trace()
7
8 B-> stack.append(raw_input('Enter New String: ').strip())
9
10 def popit():
11 if len(stack) == 0:
12 print "Cannot pop from an empty stack!"
13 else:
(Pdb) n
Enter New String: 'jmilkfan'
--Return--
> d:\development\python27\workspace\stack_demo.py(8)pushit()->None
-> stack.append(raw_input('Enter New String: ').strip())
(Pdb) w # 打印当前位置
d:\development\python27\lib\bdb.py(400)run()
-> exec cmd in globals, locals
<string>(1)<module>()
d:\development\python27\workspace\stack_demo.py(49)<module>()
-> showmenu()
d:\development\python27\workspace\stack_demo.py(46)showmenu()
-> CMDs[choice]()
> d:\development\python27\workspace\stack_demo.py(8)pushit()->None
-> stack.append(raw_input('Enter New String: ').strip())
(Pdb) p stack # 输出一个变量的值
["'jmilkfan'"]
(Pdb) !stack = ["fanguiju"] # 改变一个变量的值
(Pdb) p stack
['fanguiju']
(Pdb) c # 继续往下执行
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: q
You picked: [q]
The program finished and will be restarted
> d:\development\python27\workspace\stack_demo.py(1)<module>()
-> stack = []
(Pdb) q # 退出调试
- 在源码内直接使用
In [8]: run stack_demo.py
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: u
You picked: [u]
> d:\development\python27\workspace\stack_demo.py(8)pushit()
-> stack.append(raw_input('Enter New String: ').strip()) # 开始进入调试,该语句的前一条语句为 pdb.set_trace()
(Pdb) l
3 def pushit():
4
5 import pdb
6 pdb.set_trace()
7
8 -> stack.append(raw_input('Enter New String: ').strip())
9
10 def popit():
11 if len(stack) == 0:
12 print "Cannot pop from an empty stack!"
13 else:
(Pdb) j 16 # 不能跳转到还没有执行过的代码行
*** Jump failed: line 16 comes after the current code block
(Pdb) j 3
> d:\development\python27\workspace\stack_demo.py(3)pushit()
-> def pushit():
(Pdb) s # 进入一个函数内部
> d:\development\python27\workspace\stack_demo.py(6)pushit()
-> pdb.set_trace()
(Pdb) s # 还可以进入到调用函数的内部
--Call--
> d:\development\python27\lib\pdb.py(1250)set_trace()
-> def set_trace():
(Pdb) c # 继续执行代码
> d:\development\python27\workspace\stack_demo.py(8)pushit()
-> stack.append(raw_input('Enter New String: ').strip())
(Pdb) r # 执行代码直到从当前函数返回
Enter New String: 'jmilkfan'
--Return--
> d:\development\python27\workspace\stack_demo.py(8)pushit()->None
-> stack.append(raw_input('Enter New String: ').strip())
(Pdb) l
25 (V)iew
26 (Q)uit
27
28 Enter choice: """
29
30 -> while True:
31 while True:
32 try:
33 choice = raw_input(pr).strip()[0].lower()
34 except (EOFError, KeyboardInterrupt, IndexError):
35 choice = 'q'
(Pdb) c
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: u
You picked: [u]
> d:\development\python27\workspace\stack_demo.py(8)pushit()
-> stack.append(raw_input('Enter New String: ').strip())
(Pdb) s
--Call--
> d:\development\python27\lib\site-packages\win_unicode_console\raw_input.py(71)raw_input()
-> def raw_input(prompt=""):
(Pdb) p pr
'\n\tp(U)sh\n\tp(O)p\n\t(V)iew\n\t(Q)uit\n\t\n\tEnter choice: '
(Pdb) n
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: v
> d:\development\python27\workspace\stack_demo.py(37)showmenu()
-> print '\nYou picked: [%s]' % choice
(Pdb) n
You picked: [v]
> d:\development\python27\workspace\stack_demo.py(38)showmenu()
-> if choice not in 'uovq':
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(41)showmenu()
-> break
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(44)showmenu()
-> if choice == 'q':
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(46)showmenu()
-> CMDs[choice]()
(Pdb) n
[u"'jmilkfan'", u"'fanguiju'", u"'fanguiju'"]
> d:\development\python27\workspace\stack_demo.py(30)showmenu()
-> while True:
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(31)showmenu()
-> while True:
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(32)showmenu()
-> try:
(Pdb) n
> d:\development\python27\workspace\stack_demo.py(33)showmenu()
-> choice = raw_input(pr).strip()[0].lower()
(Pdb) n
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: v
> d:\development\python27\workspace\stack_demo.py(37)showmenu()
-> print '\nYou picked: [%s]' % choice
(Pdb) c
You picked: [v]
[u"'jmilkfan'", u"'fanguiju'", u"'fanguiju'"]
p(U)sh
p(O)p
(V)iew
(Q)uit
Enter choice: 0
IPython 自带的 Debug 工具 ipdb
基本用法跟 pdb 一样,优点在于很 IPython 结合使用能更方便的完成一个功能,也更加清晰。
In [1]: run -d stack_demo.py
Breakpoint 1 at d:\development\python27\workspace\stack_demo.py:1
NOTE: Enter 'c' at the ipdb> prompt to continue execution.
> d:\development\python27\workspace\stack_demo.py(1)<module>()
1---> 1 stack = []
2
3 def pushit():
4
5 stack.append(raw_input('Enter New String: ').strip())
ipdb> h
Documented commands (type help <topic>):
========================================
EOF bt cont enable jump pdef psource run unt
a c continue exit l pdoc q s until
alias cl d h list pfile quit step up
args clear debug help n pinfo r tbreak w
b commands disable ignore next pinfo2 restart u whatis
break condition down j p pp return unalias where
Miscellaneous help topics:
==========================
exec pdb
Undocumented commands:
======================
ll longlist retval rv
ipdb>