调试技巧
本教程共 70 篇 · 第 40 篇 · 更新于 2026-07-22 · 约 6 分钟阅读
40. 调试技巧
本节目标:掌握从简单到复杂的四种调试手段,能根据场景选择 print、assert、logging 或 pdb。
代码写了难免出 bug。发现问题后,定位根因的速度决定了你的效率。这一章介绍 Python 里常用的调试工具,从「土办法」到「专业工具」都有。
第一招:print 调试法
别笑,print() 是最快、最直接的调试方式。变量值不对?打印出来看看。
def calculate_discount(price, level):
print(f"[DEBUG] price={price}, level={level}")
if level == 'vip':
return price * 0.8
return price
result = calculate_discount(100, 'vip')
print(f"[DEBUG] result={result}")
进阶一点,用 f-string 的 = 语法(Python 3.8+):
x = 10
print(f"{x=}") # x=10
print(f"{x * 2=}") # x * 2=20
Tip
第二招:assert 断言
assert 后面跟一个条件,条件为假时抛 AssertionError:
def divide(a, b):
assert b != 0, "除数不能为零"
return a / b
# divide(10, 0) # AssertionError: 除数不能为零
断言用来检查「不应该发生」的情况。它是给开发者看的,不是给用户看的错误处理。
Warning运行 Python 时加
-O参数(优化模式),所有assert会被跳过。所以永远不要把关键的业务校验放在assert里。python -O myscript.py
第三招:logging 日志
print 的输出混杂在程序正常输出里,很难区分。logging 模块提供了分级别的日志系统:
import logging
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logging.debug('这是调试信息')
logging.info('程序正常启动')
logging.warning('磁盘空间不足 10%')
logging.error('数据库连接失败')
logging.critical('系统崩溃,立即处理')
日志级别从低到高:DEBUG < INFO < WARNING < ERROR < CRITICAL。设置 level=logging.INFO 后,debug 级别的日志不会输出。
Note生产环境不要把日志直接打屏幕,应该写到文件:
filename='app.log'。还可以按大小或日期切割,避免单个文件过大。logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s', filename='app.log', encoding='utf-8' )
日志比 print 专业得多,但配置略复杂。项目里建议统一封装一个日志模块,各业务代码直接调用。
第四招:pdb 交互式调试
遇到复杂逻辑,print 要打很多行,还容易看错。pdb(Python Debugger)让你像操作 IDE 一样,在代码执行过程中暂停、查看、单步跟踪。
在代码里插入断点
import pdb
def complex_calculation(a, b, c):
x = a + b
pdb.set_trace() # 执行到这里会暂停
y = x * c
return y
complex_calculation(1, 2, 3)
运行后,程序在 pdb.set_trace() 处暂停,进入交互式调试模式。常用命令:
| 命令 | 简写 | 作用 |
|---|---|---|
next | n | 执行下一行,不进入函数内部 |
step | s | 执行下一行,进入函数内部 |
continue | c | 继续执行,直到下一个断点 |
print | p | 打印变量值,如 p x |
list | l | 显示当前代码上下文 |
quit | q | 退出调试 |
Python 3.7+ 的断点函数
Python 3.7 引入了 breakpoint(),它是 pdb.set_trace() 的现代化替代品:
def complex_calculation(a, b, c):
x = a + b
breakpoint() # 更简洁的断点
y = x * c
return y
功能完全一样,但写法更短,而且可以通过环境变量切换不同的调试后端。
Tip如果你用 VSCode 或 PyCharm,直接在代码行号左边点一下就能设断点,体验比 pdb 好很多。但 pdb 不依赖任何 IDE,在服务器上调试时它是唯一选择。
第五招:traceback 分析
程序崩溃时,Python 会打印 traceback(回溯信息)。学会读懂它,能帮你快速定位问题。
def foo():
bar()
def bar():
1 / 0
foo()
报错输出:
Traceback (most recent call last):
File "demo.py", line 9, in <module>
foo()
File "demo.py", line 2, in foo
bar()
File "demo.py", line 6, in bar
1 / 0
ZeroDivisionError: division by zero
阅读顺序:从下往上。最下面一行是「根因」:ZeroDivisionError: division by zero。往上是调用链:bar() 被 foo() 调用,foo() 在模块顶层被调用。
Note如果报错信息里出现了你写的代码和第三方库的代码混在一起,重点看「文件路径属于你项目」的那些行。第三方库的 bug 比较少见,问题大概率出在你的调用方式上。
调试策略的选择
| 场景 | 推荐工具 |
|---|---|
| 临时看一眼变量值 | print() / f-string |
| 检查内部不变量(开发时) | assert |
| 线上环境记录运行状态 | logging |
| 复杂逻辑逐步跟踪 | pdb / IDE 断点 |
| 分析崩溃原因 | 阅读 traceback |
没有最好的工具,只有最合适的工具。小脚本用 print 最快,线上服务必须用 logging,复杂算法用 pdb 最稳。
小结
print最直接,用完记得清理。assert做内部检查,不要用于业务校验。logging是生产环境的标配,分级别、可持久化。pdb/breakpoint()让程序暂停,逐步排查。- 读懂
traceback是基本功,从下往上读。
调试是编程的一部分,不是「代码写错了才需要」。老手和新手的区别,往往在于定位问题的速度。多练几种工具,遇到 bug 时才不会手忙脚乱。
来源:参考了 liaoxuefeng「调试」、runoob「Python3 错误和异常」等,改写后所得。