第一招:读 traceback

Traceback (most recent call last):
  File "app.py", line 12, in <module>
    main()
  File "app.py", line 8, in main
    process(data)
  File "app.py", line 4, in process
    result = data["count"] / 0
ZeroDivisionError: division by zero

读 traceback 的顺序:

  1. 最后一行:错误类型 + 描述(这里是 ZeroDivisionError)
  2. 倒数最近的 File 行:错误发生的位置(app.py:4)
  3. 往上看:调用链——谁调谁导致到这一步

报错先看最后一行,看不懂再往上读。

第二招:print 调试(也叫"原始日志大法")

最快、最不需要工具:

def calc(x):
    print(f"DEBUG: x = {x}")    # 临时塞
    result = x ** 2
    print(f"DEBUG: result = {result}")
    return result

Python 3.8+ 的 f"{x=}" 让这事更优雅:

print(f"{x=}")              # x=42
print(f"{result=}")         # result=1764

调完记得删——不然代码到处是 DEBUG。

第三招:breakpoint() — 内置断点

def calc(x):
    breakpoint()            # 跑到这就停
    return x ** 2

python app.py,会进入 pdb 交互:

> /path/to/app.py(2)calc()
-> return x ** 2
(Pdb)

常用命令:

命令 作用
n (next) 执行下一行
s (step) 步入函数
c (continue) 继续到下一个断点 / 结束
l (list) 显示当前位置代码
p x 打印变量
pp x 漂亮打印(pretty print)
w (where) 显示调用栈
u / d 调用栈上下移动
q 退出

第四招:IDE 调试器

VS Code / PyCharm 的图形化调试器最强:

  • 鼠标点行号 = 设断点
  • F5 启动调试
  • 左侧面板看变量
  • 鼠标悬停看任何表达式的值
  • 条件断点("x > 10 时才停")
  • 调用栈点击跳转

写大项目优先用 IDE 调试

第五招:post-mortem(事后调试)

崩了之后进入崩溃现场:

python -m pdb app.py

或在代码里:

import sys
import pdb

def excepthook(t, v, tb):
    pdb.post_mortem(tb)

sys.excepthook = excepthook

崩了不退出,自动进入 pdb——你可以查崩溃时所有变量。

第六招:rich 的 traceback

pip install rich
from rich.traceback import install
install(show_locals=True)

崩溃时彩色显示 traceback + 自动展开局部变量——比原版强 10 倍。

第七招:日志 + log_level

线上环境不方便加断点——靠日志:

logger.debug(f"输入: {x}")
result = expensive_calc(x)
logger.debug(f"输出: {result}")

平时 INFO 级别,有问题时改成 DEBUG,重跑或重启即可看到所有细节。

第八招:用最小复现

定位 bug 的终极武器:

  1. 把出问题的代码逐步精简
  2. 每次删一段,看还能不能复现
  3. 直到只剩 5 行还能复现 → bug 就在这 5 行里

这套方法 80% 的难题都能定位。

调试心态

"Don't guess. Verify."

不要靠猜。把每一步都打印出来 / 单步执行,直到亲眼看到错误发生的瞬间。

下一篇讲性能调优