2. 断点基础
调试这件事,说白了就是让代码停下来,然后你好好看看它到底在干什么。而断点,就是那个让代码停下来的“暂停键”。
我刚开始写代码那会儿,调试全靠print大法。满屏的print语句,调试完还得一个个删,删漏了还会出bug。后来学会了断点,才明白什么叫“事半功倍”。今天咱们就把断点这事儿彻底聊透。
断点的概念:代码执行的“定格”
断点是什么?简单说,就是你告诉调试器:“嘿,执行到这一行的时候,先停一下,让我看看情况。”
代码一旦停在断点处,当前所有变量的值、调用栈的信息、线程的状态,全都被冻结了。你可以慢慢检查,逐行往下走,甚至修改变量的值再继续执行。
核心要点:断点不会修改你的代码,它只是调试器的一个标记。你随时可以启用、禁用或删除它。
我记得有一次排查一个线上bug,代码跑了几个小时才复现。如果用print,得重新跑一遍,还得祈祷日志打全了。但用断点,我直接在可疑位置设个断点,等它命中就行。嗯,这就是断点的价值。
行断点设置:最基础也最常用
行断点,就是你在某一行代码上设一个断点。执行到这一行时,调试器就会停下来。
设置方法很简单:
- VS Code / PyCharm:在行号左侧点击一下,出现红色圆点
- 命令行调试(pdb):在代码中插入
import pdb; pdb.set_trace() - 浏览器开发者工具:在Sources面板点击行号
# 示例:一个简单的行断点
def calculate_discount(price, rate):
discount = price * rate # 在这里设断点
final_price = price - discount # 或者在这里
return final_price
# 调用函数
result = calculate_discount(100, 0.2)
print(result)
你想想看,当代码停在 discount = price * rate 这一行时,你可以检查 price 和 rate 的值对不对。如果 rate 传成了0.8,那折扣就变成80块了,明显不合理。
我的习惯:在函数的第一行和关键计算行各设一个断点。第一行确认参数是否正确,关键行确认逻辑是否正确。这样两步走,大部分bug都能定位到。
条件断点设置:只在需要的时候停下来
行断点有个问题——每次执行到那一行都会停。如果函数被调用了1000次,你就要手动点1000次“继续”。这谁受得了?
条件断点就是解决方案。你可以设置一个条件,只有条件满足时,断点才会触发。
# 场景:处理用户订单,只排查订单金额大于10000的情况
def process_order(order_id, amount):
# 在这里设条件断点:amount > 10000
print(f"Processing order {order_id}")
# ... 其他逻辑
for i in range(1, 1001):
process_order(i, i * 10) # 金额从10到10000
设置条件断点的方法:
- VS Code:右键红色断点 → Edit Breakpoint → 输入条件表达式
- PyCharm:右键断点 → 输入Condition
- pdb:使用
pdb.set_trace()配合 if 语句
我曾经踩过的坑:条件表达式写错了类型。比如 amount 是字符串,我写成了 amount > 10000,结果断点永远不触发。排查了半天才发现是类型问题。所以,写条件时一定要确认变量的类型。
条件断点还有一个妙用——调试循环中的特定迭代。比如循环100次,我只想看第50次的情况:
for i in range(100):
# 条件断点:i == 50
process_item(i)
临时断点:一次性使用的“侦察兵”
临时断点,说白了就是“用完即弃”的断点。它触发一次后,自动删除。
什么时候用?我举个例子:
你在调试一个递归函数,想知道第一次进入递归时的状态。但递归会调用很多次,你不想每次都停。这时候,临时断点就派上用场了。
def factorial(n):
if n <= 1:
return 1
# 在这里设临时断点,只停一次
result = n * factorial(n - 1)
return result
# 调用时,临时断点只在第一次进入时触发
print(factorial(5))
设置方法:
- VS Code:右键行号 → Add Conditional Breakpoint → 勾选“Hit Count”设为1
- PyCharm:右键断点 → 勾选“Remove once hit”
- pdb:使用
pdb.set_trace()配合计数器变量
我的经验:临时断点特别适合调试“首次执行”的逻辑。比如初始化代码、单例模式的首次创建、缓存未命中时的首次加载。这些场景下,你只关心第一次执行的情况,后面都是重复的。
三种断点的对比
| 断点类型 | 触发方式 | 适用场景 | 我的使用频率 |
|---|---|---|---|
| 行断点 | 每次执行到该行 | 简单逻辑、少量调用 | 60% |
| 条件断点 | 满足条件时触发 | 循环、高频调用、特定数据 | 30% |
| 临时断点 | 触发一次后自动删除 | 首次执行、递归入口 | 10% |
知识体系总览
下面这张图,帮你把断点的核心逻辑串起来:
这张图把三种断点的关系讲得很清楚。你想想看,从中心出发,根据你的调试需求,选择最合适的断点类型。我个人建议,能用条件断点就别用行断点,能少停就少停,调试效率会高很多。
一句话总结:行断点让你看到“发生了什么”,条件断点让你看到“什么时候发生”,临时断点让你看到“第一次发生了什么”。三种配合使用,没有调不了的bug。
好了,断点基础就聊到这儿。记住,调试不是靠运气,而是靠工具。断点就是你手里最趁手的工具之一。多用、多练,慢慢你就会发现,调试其实比写代码还有意思。
可可精品资料库