Python 调试工具 pdb
pdb(Python Debugger)是Python内置的调试模块,允许开发者在代码运行时设置断点、检查变量、逐步执行代码,是调试复杂程序的强大工具。
1. 启动pdb
pdb可以通过多种方式启动,以下是最常用的方法:
1.1 在命令行运行pdb
通过在命令行中运行Python脚本并添加-m pdb
参数,可以直接启动pdb。例如:
# 示例代码:simple_calc.py
def add(a, b):
result = a + b
return result
x = 10
y = 5
z = add(x, y)
print(f"Result: {z}")
在终端运行:
python -m pdb simple_calc.py
运行后,pdb会暂停在代码的第一行,显示(Pdb)
提示符,进入交互模式。
1.2 在代码中嵌入pdb
在代码中插入pdb.set_trace()
,程序会在该位置暂停并进入pdb调试模式。例如:
# 示例代码:embedded_pdb.py
import pdb
def multiply(a, b):
result = a * b
pdb.set_trace() # 程序在这里暂停
return result
x = 3
y = 4
z = multiply(x, y)
print(f"Result: {z}")
运行后,程序会在pdb.set_trace()
处暂停,进入交互模式。
2. pdb基本命令
进入pdb后,可以使用一系列命令控制程序执行。以下是常用命令:
- h(elp):显示所有命令或某个命令的帮助。例如,
h
显示所有命令,h n
显示next
命令的帮助。 - n(ext):执行当前行代码,移动到下一行(不进入函数)。
- s(tep):执行当前行代码,若为函数调用,则进入函数内部。
- c(ontinue):继续执行直到遇到下一个断点或程序结束。
- q(uit):退出pdb。
- l(ist):显示当前代码的上下文(默认11行,当前行居中)。
- p:打印表达式的值。例如,
p x
打印变量x
的值。
示例代码:
# 示例代码:basic_commands.py
import pdb
def divide(a, b):
pdb.set_trace() # 暂停以进入pdb
result = a / b
return result
x = 10
y = 2
z = divide(x, y)
print(f"Result: {z}")
运行后,在(Pdb)
提示符下:
- 输入
p x
查看x
的值(结果:10
)。 - 输入
n
执行到下一行。 - 输入
l
查看当前代码上下文。
3. 设置和管理断点
断点允许开发者在特定代码行暂停执行。pdb提供以下断点相关命令:
- b(reak) [lineno | function]:设置断点。例如,
b 5
在第5行设置断点,b divide
在函数divide
入口设置断点。 - cl(ear) [bpnumber]:清除断点。例如,
cl 1
清除编号为1的断点。 - disable [bpnumber]:禁用断点,但保留断点信息。
- enable [bpnumber]:启用已禁用的断点。
- breakpoints:列出所有断点。
示例代码:
# 示例代码:breakpoints.py
import pdb
def calculate_sum(n):
total = 0
for i in range(n):
total += i
return total
pdb.set_trace()
n = 5
result = calculate_sum(n)
print(f"Sum: {result}")
运行后,在(Pdb)
提示符下:
- 输入
b calculate_sum
在函数calculate_sum
入口设置断点。 - 输入
c
运行到断点。 - 输入
breakpoints
查看断点列表。
4. 逐步调试与变量检查
逐步调试是pdb的核心功能,结合变量检查可以快速定位问题。
4.1 逐步执行
- n(ext):执行当前行,停在下一行。
- s(tep):进入函数或执行当前行。
- r(eturn):执行到当前函数返回。
示例代码:
# 示例代码:step_debug.py
import pdb
def factorial(n):
if n == 0:
return 1
return n * factorial(n - 1)
pdb.set_trace()
result = factorial(3)
print(f"Factorial: {result}")
运行后,在(Pdb)
提示符下:
- 输入
s
进入factorial
函数。 - 输入
n
逐步执行,观察递归过程。 - 输入
p n
检查变量n
的值。
4.2 检查与修改变量
- p:打印变量值。
- !variable = value:修改变量值。例如,
!x = 100
将变量x
的值改为100。
示例代码:
# 示例代码:variable_check.py
import pdb
def process_data(data):
pdb.set_trace()
data.append(100)
return data
values = [1, 2, 3]
result = process_data(values)
print(f"Result: {result}")
运行后,在(Pdb)
提示符下:
- 输入
p data
查看data
的值(结果:[1, 2, 3]
)。 - 输入
!data[0] = 99
修改data
的第一个元素。 - 输入
p data
确认修改(结果:[99, 2, 3]
)。
5. 条件断点与异常调试
5.1 条件断点
通过b [lineno], condition
设置条件断点,仅在条件为真时暂停。例如,b 5, i > 2
在第5行当i > 2
时暂停。
示例代码:
# 示例代码:conditional_break.py
import pdb
def sum_numbers(n):
total = 0
for i in range(n):
total += i
return total
pdb.set_trace()
result = sum_numbers(5)
print(f"Sum: {result}")
运行后,在(Pdb)
提示符下:
- 输入
b 5, i > 2
在第5行(循环内)设置条件断点。 - 输入
c
运行,程序仅在i > 2
时暂停。
5.2 调试异常
pdb可以在异常发生时自动进入调试模式。使用post_mortem
模式捕获异常:
# 示例代码:exception_debug.py
import pdb
def divide_numbers(a, b):
result = a / b
return result
try:
result = divide_numbers(10, 0)
print(f"Result: {result}")
except ZeroDivisionError:
pdb.post_mortem()
运行后,程序因除零异常暂停,进入pdb,开发者可以检查调用栈和变量。
6. 高级功能
6.1 调用栈导航
- w(here):显示当前调用栈。
- u(p):移动到上层调用栈。
- d(own):移动到下层调用栈。
示例代码:
# 示例代码:call_stack.py
import pdb
def inner_func(x):
pdb.set_trace()
return x * 2
def outer_func(y):
result = inner_func(y)
return result
value = 5
result = outer_func(value)
print(f"Result: {result}")
运行后,在(Pdb)
提示符下:
- 输入
w
查看调用栈。 - 输入
u
移动到outer_func
。 - 输入
p y
检查y
的值。
6.2 交互式执行
使用interact
命令进入Python交互模式,可以运行任意Python代码。
示例代码:
# 示例代码:interactive.py
import pdb
def compute_square(n):
pdb.set_trace()
return n * n
value = 4
result = compute_square(value)
print(f"Square: {result}")
运行后,在(Pdb)
提示符下:
- 输入
interact
进入Python交互模式。 - 输入
print(n * 3)
计算并打印n * 3
。