$PDB——Python调试利器详解
python 2.7 pdb官方文档:https://docs.python.org/2.7/library/pdb.html
pdb是ptyhon内置的一个调试库,是调试python代码的好帮手,本文是对其用法的详细介绍。
QuickStart
待调试的代码内容
文件名:test.py:
# coding:utf-8
import pdb
s1 = 'aaa'
pdb.set_trace()
s2 = 'bbb'
s3 = 'ccc'
pdb.set_trace()
s = s1 + s2 + s3
print s
可以看出在代码的第4、7行分别打了一个断点,使用的是pdb.set_trace()函数。
开始调试
在和代码文件相同路径下打开命令行窗口,输入命令:python test1.py
接着就进入了调试状态:
(.env) E:\code\python-basic\tools\pdb\sample>python test1.py
> e:\code\python-basic\tools\pdb\sample\test1.py(5)<module>()
-> s2 = 'bbb'
(Pdb)
可以看出直接执行到了第一个断点所在的下一行,并停在了这里。
这时可以执行命令:n进行下一步:
(Pdb) n
> e:\code\python-basic\tools\pdb\sample\test1.py(6)<module>()
-> s3 = 'ccc'
(Pdb)
使用p <变量名>命令打印已经出现过的变量的值:
(Pdb) p s1
'aaa'
(Pdb) p s2
'bbb'
(Pdb) p s3
*** NameError: NameError("name 's3' is not defined",)
(Pdb)
因为当前变量s3还没有被赋值,所以打印s3的时候提示NameError异常。
使用l命令打印出当前的代码段:
(Pdb) l
1 # coding:utf-8
2 import pdb
3 s1 = 'aaa'
4 pdb.set_trace()
5 s2 = 'bbb'
6 -> s3 = 'ccc'
7 pdb.set_trace()
8 s = s1 + s2 + s3
9 print s
[EOF]
(Pdb)
退出调试:q命令
(Pdb) q
Traceback (most recent call last):
File "test1.py", line 6, in <module>
s3 = 'ccc'
File "test1.py", line 6, in <module>
s3 = 'ccc'
File "d:\programs\python27\Lib\bdb.py", line 49, in trace_dispatch
return self.dispatch_line(frame)
File "d:\programs\python27\Lib\bdb.py", line 68, in dispatch_line
if self.quitting: raise BdbQuit
bdb.BdbQuit
(.env) E:\code\python-basic\tools\pdb\sample>
PDB调试的另一种方式
QuickStart中使用的调试方式不够优雅,因为是通过修改代码的方式打断点的,用起来不太方便。那么能不能动态打断点呢?答案是当然可以,请接着往下看。
准备待调试的代码
删除掉QuickStart中代码中的pdb.set_trace(),剩下的代码如下:
文件名:test2.py
# coding:utf-8
s1 = 'aaa'
s2 = 'bbb'
s3 = 'ccc'
s = s1 + s2 + s3
print s
开始调试
在test2.py相同路径下打开命令行,输入命令:python -m pdb test2.py
(.env) E:\code\python-basic\tools\pdb\sample>python -m pdb test2.py
> e:\code\python-basic\tools\pdb\sample\test2.py(2)<module>()
-> s1 = 'aaa'
(Pdb) l
1 # coding:utf-8
2 -> s1 = 'aaa'
3 s2 = 'bbb'
4 s3 = 'ccc'
5 s = s1 + s2 + s3
6 print s
[EOF]
(Pdb)
可以看到当前代码中我们还没有打任何断点,代码默认停在了第1行。
执行一个命令n:
(Pdb) n
> e:\code\python-basic\tools\pdb\sample\test2.py(3)<module>()
-> s2 = 'bbb'
(Pdb) l
1 # coding:utf-8
2 s1 = 'aaa'
3 -> s2 = 'bbb'
4 s3 = 'ccc'
5 s = s1 + s2 + s3
6 print s
[EOF]
(Pdb)
可以看到单步执行到了下一行。
如果我们想在第5行打一个断点,该怎么打呢?用b <行号>命令在某一行打一个断点:
(Pdb) b 5
Breakpoint 1 at e:\code\python-basic\tools\pdb\sample\test2.py:5
(Pdb) l
[EOF]
(Pdb) n
> e:\code\python-basic\tools\pdb\sample\test2.py(4)<module>()
-> s3 = 'ccc'
(Pdb) l
1 # coding:utf-8
2 s1 = 'aaa'
3 s2 = 'bbb'
4 -> s3 = 'ccc'
5 B s = s1 + s2 + s3
6 print s
[EOF]
(Pdb)
这样就成功地在第5行打了一个断点。
查看当前打了哪些断点:b命令
(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at e:\code\python-basic\tools\pdb\sample\test2.py:5
(Pdb)
PDB调试命令汇总
高级命令
以上的示例只是展示了最简单的顺序结构的代码的调试方法,而实际应用中遇到的大多数代码都有着较为复杂的逻辑结构,比如循环结构、分支结构、调用函数、调用其他模块的函数、使用类和对象等等。
针对这些场景还有很多更高级的调试命令,其实掌握了前面的几个简单的命令的用法后,下面的这些更高级的命令就都很容易上手了,多用几遍就能很快掌握了。
| 命令 | 命令全称 | 功能 |
|---|---|---|
| h | help | 查看帮助 |
| n | next | 执行下一条语句 |
| s | step | 执行下一条语句,如果是函数,则会执行到函数的第一句 |
| b | break | 列出当前的所有断点 |
| b <行号> | / | 在某一行打一个断点 |
| b <文件名>:<行号> | / | 在某个文件的某行打一个断点 |
| b <函数名> | / | 在某个函数的第一行打一个断点 |
| cl | clear | 清除所有断点 |
| cl n1 n2 ... | / | 清除编号为n1、n2...的断点 |
| cl <行号> | / | 清除某行的断点 |
| cl <文件名>:<行号> | / | 清除某个文件某行的断点 |
| r | return | 执行当前函数到结束 |
| c | continue | 执行到下一个断点 |
| l | list | 列出源码(前后11行代码) |
| l <行号> | / | 列出某行周围11行代码 |
| l <行号1> <行号2> | / | 列出两个行号范围内的代码 |
| p <变量名> | print <变量名> | 输出变量的值 |
| pp <变量名> | / | 好看一点的输出 |
| q | quit | 退出debug |
| unt | until | 退出循环或当期堆栈 |
| run | / | 重新启动debug |
| a | args | 列出当前执行的函数的参数 |
| w | where | 打印当前执行堆栈 |
注:平时使用的时候通常用的都是各个命令的简写形式,当然用全称也是可以的(如果不嫌麻烦的话)。
补充
- 在命令行中进入调试模式的方法:
python -m pdb demo.py - 在调试模式中按一下
Enter键表示执行一下上一条命令。
随机推荐
- vue2.0非父子间进行通讯
在vue中,父组件向之组件通讯使用的是props,子组件向父组件通讯使用的是$emit+事件,那非父子间的通讯呢,在官方文档上只有寥寥数笔, 概念很模糊,这个空的vue实例应该放在哪里呢,光放文档并没 ...
- 【BZOJ5083】普及 单调栈+二分+RMQ
[BZOJ5083]普及 Description 有一个长度为n的字符串,每一位只会是p或j.你需要取出一个子串S(从左到右或从右到左一个一个取出),使得 不管是从左往右还是从右往左取,都保证每时每刻 ...
- 《从零开始学Swift》学习笔记(Day 10)——运算符是“ +、-、*、/ ”吗?
原创文章,欢迎转载.转载请注明:关东升的博客 运算符是用于执行程序代码运算,会针对一个或一个以上操作数项目来进行运算.例如:2+3,其操作数是2和3,而运算符则是“+”.那么“+.-.*./”是运算符 ...
- 160229-01、web页面常用功能js实现
web页面常用功能js实现 1.网页未加载时弹出新窗口 <body onunload="window.open('http://www.a68.cn');">< ...
- sssssss
1dispatcherServlet—拦截到spring mvc的请求 2dispatchServlet调用HandlerMapping( DefaultAnnoationHandlerMapping ...
- Webpack4.x 入门
概览 新建项目 npm init -y 安装webpack & webpack-cli (c)npm install -D webpack (c)npm install -D webpack- ...
- 剑指Offer——数组中出现次数超过一半的数字
题目描述: 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2 ...
- Python自省(反射)指南(转)
原文:http://www.cnblogs.com/huxi/archive/2011/01/02/1924317.html 在笔者看来,自省和反射是一回事,当然其实我并不十分确定一定以及肯定,所以如 ...
- Flask之视图函数
视图示例 @app.route('/hello') def hello(): return 'Hello World' if __name__ == '__main__': app.run() 特殊的 ...
- goland激活
http://blog.csdn.net/benben_2015/article/details/78725467 http://blog.csdn.net/john_f_lau/article/de ...