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键表示执行一下上一条命令。

随机推荐

  1. WPF 附加事件

    在WPF中有许多控件有他们自己的特殊的事件.按钮就是一个例子——它添加了 Click 事件,而其他任何类都没有定义该事件. 这回导致两难的境地.假设在 StackPanel 面板中包装了一堆按钮,并且 ...

  2. 提高ASP.NET网站性能的方法

    http://www.360doc.com/content/14/0705/18/7662927_392224856.shtml   Asp.NET有许多秘密,当你了解了这些秘密后,可以使得你的ASP ...

  3. iOS开发之--实现倒计时显示时分秒

    这段时间写公司的一个外包项目,需要用到倒计时:需要显示时分秒,通过在网上搜集资料,找到了2中方法,我把这两种方法结合起来,可以很好的满足这个需求: 1.创建一个类继承自UIlabel,用来展示时分秒的 ...

  4. JqGrid 获取所有数据

    jqGrid使用本地数据时,当jqGrid配置的rowNum小于本地总数据量(records属性记录总数据,可以通过records获取到本地总数据量),调用getRowData方法获取到的只是显示的部 ...

  5. 【BZOJ4864】[BeiJing 2017 Wc]神秘物质 Splay

    [BZOJ4864][BeiJing 2017 Wc]神秘物质 Description 21ZZ 年,冬. 小诚退休以后, 不知为何重新燃起了对物理学的兴趣. 他从研究所借了些实验仪器,整天研究各种微 ...

  6. Convolution Matrix

    w褶积矩阵.二值化旧图经核矩阵得到新图. https://docs.gimp.org/en/plug-in-convmatrix.html 8.2. Convolution Matrix 8.2.1. ...

  7. 设计模式——抽象工厂模式

    Abstract Factory模式,即抽象工厂模式,该模式要求Factory类为抽象的,并且里面的生产出来的产品也是抽象的! 这里需要着重说的一点就是,抽象类和抽象方法的作用--规范了子类的实现,以 ...

  8. 使用 postMessage + iframe 实现跨域通信

    一.postMessage window.postMessage() 方法可以安全地实现跨源通信.通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(44 ...

  9. 转!!mybatis xml 传值 if test判断

    当mapper方法传参数 为 String时,且xml中药进行参数比较 比如 是不是等于1 或者等于2 方式1. 方式2. 转自:https://blog.csdn.net/chenaini119/a ...

  10. nginx日志配置(cookie,header,post等字段记录)

    如果你对nginx日志格式,有这样那样的要求. 那么就看一下说明吧. $remote_addr The remote host $remote_user The authenticated user ...