
调试代码是每个程序员都要面对的事,尤其是当代码跑起来莫名其妙出错的时候,Python 自带的调试工具 pdb 就是个救命神器!
它虽然没有图形化调试工具那么花哨,但简单好用,特别适合快速定位问题。这篇文章会带你从零开始,逐步搞懂 pdb 的用法,适合新手也能上手。
参考文章:Python 调试工具 pdb | 简单一点学习 easyeasy.me
pdb 是 Python 的内置调试模块,全称是 Python Debugger。它能让你在代码运行时暂停程序,检查变量值、逐步执行代码、甚至动态修改代码逻辑。不需要装啥额外的东西,Python 自带,随时可用。
用 pdb,你可以:
有几种方法可以启动 pdb,咱们先从最简单的开始讲。
最直接的方式就是在代码里手动插入 pdb.set_trace(),程序运行到这行就会暂停,进入调试模式。比如:
def add_numbers(a, b):
result = a + b
import pdb; pdb.set_trace() # 在这里暂停
return result
print(add_numbers(3, 5))运行这段代码,程序会在 pdb.set_trace() 处停下来,你会看到一个交互式提示符 (Pdb),可以开始输入调试命令了。
Python 3.7+ 的改进:从 Python 3.7 开始,你可以用更简单的 breakpoint() 函数代替 import pdb; pdb.set_trace(),效果一样:
def add_numbers(a, b):
result = a + b
breakpoint() # 更简洁
return result
print(add_numbers(3, 5))如果你不想改代码,可以直接在命令行用 python -m pdb your_script.py 运行脚本。pdb 会从代码的第一行开始,进入调试模式。
比如,假设你有个脚本 script.py:
def divide(a, b):
result = a / b
return result
print(divide(10, 0)) # 这里会出错用命令行运行:
python -m pdb script.py程序会停在第一行,你可以用 n(下一行)或 s(步入函数)逐步执行,很快就能发现除零错误。
如果代码抛出异常,想直接跳到出错的地方调试,可以用 pdb.post_mortem()。不过更简单的方法是用 python -m pdb -c continue your_script.py,程序会在抛出异常时自动进入调试模式。
比如,运行上面的 script.py:
python -m pdb -c continue script.py程序会在除零错误发生时停下来,进入 (Pdb) 模式,方便你检查变量和调用栈。
进入 pdb 后,你会看到 (Pdb) 提示符,输入命令来控制程序。以下是最常用的命令,建议边学边试!
命令 | 缩写 | 功能 |
|---|---|---|
|
| 执行下一行代码(不进入函数内部) |
|
| 进入函数内部,逐步执行 |
|
| 继续运行,直到下一个断点或程序结束 |
|
| 设置断点,比如 |
|
| 打印变量值,比如 |
|
| 显示当前代码的上下文 |
|
| 显示调用栈 |
|
| 运行到当前函数返回 |
|
| 退出调试 |
看个例子,假设有以下代码:
def calculate_average(numbers):
total = sum(numbers)
count = len(numbers)
breakpoint()
average = total / count
return average
numbers = [1, 2, 3, 0, 5]
print(calculate_average(numbers))运行后,程序会在 breakpoint() 暂停。你可以:
p total 查看 total 的值p count 查看 count 的值n 执行下一行c 继续运行如果 numbers 是个空列表,count 会是 0,average = total / count 会抛出除零错误。调试时你就能提前发现这个问题。
手动加 breakpoint() 虽然简单,但如果想动态设置断点,可以在 (Pdb) 模式下用 break 命令。
(Pdb) b 10 # 在第10行设置断点(Pdb) b my_function # 在 my_function 函数入口设置断点(Pdb) b # 列出所有断点(Pdb) clear 1 # 删除编号为1的断点例子:
def process_data(data):
result = []
for item in data:
result.append(item * 2)
breakpoint()
return result
data = [1, 2, 3]
print(process_data(data))运行后,在 (Pdb) 模式下输入 b process_data 可以在函数入口再加一个断点,然后用 c 运行到下一个断点。
调试时,检查变量值是核心操作。可以用 p 命令打印变量,也可以用 ! 执行 Python 表达式来修改变量。
def modify_list(items):
breakpoint()
items.append(100)
return items
my_list = [1, 2, 3]
print(modify_list(my_list))在 (Pdb) 模式下:
p items 查看 items 的值,应该是 [1, 2, 3]!items.append(999) 动态添加一个元素p items 再检查,变成 [1, 2, 3, 999]c 继续运行想在特定条件下暂停? forsale
(Pdb) b 10, my_var > 5 # 当 my_var > 5 时在第10行暂停循环里调试很容易迷失方向,建议用 list 命令多看看上下文,或者用 where 检查调用栈。比如:
def sum_squares(n):
total = 0
for i in range(n):
total += i * i
breakpoint()
return total
print(sum_squares(5))在 (Pdb) 下:
p i 查看当前循环的 ip total 查看累加的结果n 逐步执行循环体如果调试命令很多,可以保存到文件里:
(Pdb) commands 1
(com) p my_var
(com) c
(end)保存后可以用 source filename 加载这些命令。
来看个稍微复杂的例子:
def process_student_scores(scores):
total = 0
count = 0
for score in scores:
if score >= 60:
total += score
count += 1
breakpoint()
average = total / count if count > 0 else 0
return average
scores = [85, 90, 55, 70, 0]
print(process_student_scores(scores))运行后,程序在 breakpoint() 暂停。你可以:
p scores 检查输入的成绩列表p total 和 p count 检查累加值和计数n 逐步执行,观察 average 计算scores 为空列表,count 会是 0,调试时就能发现潜在的除零错误list 和 where:调试时很容易迷失在代码里,这两个命令能帮你搞清楚“现在在哪”。! 修改变量:动态改变量值能帮你快速验证假设。clear 删掉不再需要的断点,避免以后运行干扰。pdb 虽然好用,但也有局限:
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。