Python 的 pdb 模块是一个可交互的源代码调试器,支持源代码级别的断点和单步调试。

Python 进入 pdb 调试模式的两种方式

1. 直接在命令行参数指定使用 pdb 模块启动 Python 文件

1
python -m pdb myscript.py

2. 在程序代码中设置断点

1
2
3
4
# 首先需要在程序中使用如下语句导入 pdb 模块:
import pdb
# 然后再在需要设置断点的地方放置如下断点设置代码:
pdb.set_trace()

pdb 的常用命令(commands)

常用命令

命令 用途
h(elp) [command] 有参数则打印 command,没参数则打印所有可用的 commands。help pdb 打印 pdb 模块的文档。
w(here) 打印堆栈信息,最新的帧在最底部。箭头表示当前帧。
b(reak) 查看断点及其编号。
b(reak) lineno 在 lineno 行打一个断点
tbreak temporary break point,一个临时的断点,只断一次。
cl(ear) lineno 清除该行的断点。
cl(ear) lineno1 lineno2 lineno3 清除该几行的断点。
cl(ear) 清楚全部断点。
n(ext) 执行下一行(不会进入函数体)
s(tep) 执行下一行(能够进入函数体)
r(eturn) 执行下一行(在函数中时会直接执行到函数返回处)
c(ont(inue)) 继续运行到下一个断点。
unt(il) [lineno] 持续执行直到运行到指定行(或遇到断点)。
l(ist) [first[, last]] 打印当前文件的源代码。
ll or longlist 打印当前 function 或 frame 的所有的源代码。
p expression 打印 expression 的值。
pp expression 打印 expression,但是 pretty-printed。
whatis expression 打印 expression 的 type。
q(uit) 中止并退出调试。

常用函数

命令 用途
dir() 打印出一个变量的列表。
locals() or vars() 打印出当前作用域中的所有变量,包括 Python 解释器自动创建的内部变量和模块级别的变量。

如果使用 locals() 函数的话,需要过滤器 print({k:v for k,v in locals().items() if k in ('x', 'y')})

实战

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/python3

# from https://www.runoob.com/python3/python3-class.html

# 类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))

# 实例化类
p = people('runoob',10,30)
p.speak()

简单调试过程如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ python -m pdb myscript.py
> /home/fdse/luorong/learn/test/myscript.py(6)<module>()
-> class people:

(Pdb) n
> /home/fdse/luorong/learn/test/myscript.py(21)<module>()
-> p = people('runoob',10,30)

(Pdb) n
> /home/fdse/luorong/learn/test/myscript.py(22)<module>()
-> p.speak()

(Pdb) dir()
['__builtins__', '__file__', '__name__', 'p', 'people']

(Pdb) b 22
Breakpoint 2 at /home/fdse/luorong/learn/test/myscript.py:22

(Pdb) b
Num Type Disp Enb Where
1 breakpoint keep yes at /home/fdse/luorong/learn/test/myscript.py:22

(Pdb) whatis p
<class '__main__.people'>

在 PDB 中,使用 b 命令后显示的参数:

  • disp 用于控制是否显示当前断点的信息。
  • enb 和 dis 用于启用和禁用断点。
  • num 用于显示断点的编号。
  • where 用于显示当前程序的调用堆栈。

参考