调试代码是每个程序员都要面对的事,尤其是当代码跑起来莫名其妙出错的时候,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
查看当前循环的 i
p 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 删除。