本文目录导读:

- 核心原则:像侦探一样思考
- 预防性调试:在写代码时就埋好“雷达”
- 基础调试法:
print语句的进阶用法 - 交互式调试器(超级推荐!)
- 利用 IDE(集成开发环境)进行可视化调试
- 针对特定场景的“急救包”
- 调试流程建议
调试自己写的实用脚本是开发者生涯中非常重要的一项技能,好的调试方法能帮你节省大量时间,还能避免一些难以发现的错误。
下面我为你整理了一套从简单到复杂、从通用到具体的调试策略,适用于常见的脚本语言(如 Python、Bash、JavaScript 等)。
核心原则:像侦探一样思考
- 复现:找到稳定触发 bug 的方法。
- 定位:从“脚本出了问题”缩小到“第 4 行出了问题”。
- 隔离:确认是输入数据、逻辑错误还是依赖问题。
- 修复:修改代码并验证。
下面是一些非常实用的调试技巧,按推荐程度排序:
预防性调试:在写代码时就埋好“雷达”
这是最高效的调试,目的不是找 bug,而是不让 bug 出现。
-
优秀的日志(Logging):不要只用
print,使用专业的日志库。-
Python:
import loggingimport logging logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') def process_data(data): logging.debug(f"输入数据: {data}") # ... 做一些操作 ... result = data['key'] # key 不存在会报错 logging.info(f"处理结果: {result}") return result -
好处:可以按级别(DEBUG, INFO, WARNING, ERROR)过滤日志,写到文件里,对生产环境非常友好。
-
-
使用断言(Assert)
- 在代码里显式声明“这个值此时不应该为 None”。
def calculate_average(grades): assert len(grades) > 0, "成绩列表不能为空!" return sum(grades) / len(grades) - 注意:断言在 Python 生产环境(
-O优化模式)下可能被关闭,所以只用于开发调试。
- 在代码里显式声明“这个值此时不应该为 None”。
基础调试法:print 语句的进阶用法
如果你的脚本很简单,或者没有安装复杂的工具,print 仍然是利器,但要用得有技巧。
-
标签化打印:不要只打印变量,要打印它“是谁”。
- ❌
print(data) - ✅
print(f"[DEBUG] 进入函数process_data,输入数据data的值为: {data[:10]}")
- ❌
-
打印关键中间状态:在循环、条件判断、函数调用前后打印。
for i, item in enumerate(list_of_items): print(f"迭代次数: {i}, 当前项: {item}") # 检查某个条件 if item < 0: print(f"[WARNING] 在第 {i} 处发现负数: {item}") -
使用
repr()而非str():当你打印字符串时,repr()能显示转义字符和特殊格式,避免被迷惑。s = "hello\nworld" print(s) # 输出两行,可能看不出换行符 print(repr(s)) # 输出 'hello\nworld'
交互式调试器(超级推荐!)
这是最专业的调试方式,适用于复杂逻辑,它让你能暂停代码,一行一行执行,并检查所有变量的值。
Python:pdb 或 ipdb (推荐 ipdb)
-
安装:
pip install ipdb -
使用:在代码中你想暂停的地方插入断点。
import ipdb def complex_function(x, y): result = x + y ipdb.set_trace() # <--- 程序会停在这里,进入交互模式 result = result * x return result -
常用命令(在交互界面输入):
n(next):执行下一行。s(step):进入函数内部。c(continue):继续执行直到下一个断点。p variable_name:打印变量的值。l(list):显示当前行附近的源代码。q(quit):退出调试器。
更现代的选择:pdb++ 或 ptvsd 但对于大多数脚本,ipdb 已经足够强大。
Node.js/JavaScript:使用 node inspect
# 在代码中插入 debugger; # 然后运行脚本 node inspect your_script.js
Bash:bash -x 或 set -x
Bash 脚本的调试比较痛苦,但也很有效。
- 全局调试:运行脚本时加上
-x参数,会打印出每一条执行的命令和参数。bash -x your_script.sh arg1 arg2
- 局部调试:在脚本里插入
set -x和set +x。echo "这是一段没有调试的信息" set -x # 开启调试 for i in 1 2 3; do echo "当前 i 的值是 $i" done set +x # 关闭调试 echo "调试结束"
利用 IDE(集成开发环境)进行可视化调试
如果你使用 VS Code,PyCharm,WebStorm 等现代 IDE,它们的图形化调试器是最直观、最强大的方式。
- 设置断点:在代码行号左侧点击一下(出现红点)。
- 点击“调试”按钮:不要点“运行”。
- 调试控制面板:
- 变量面板:实时查看所有变量的值,会自动更新。
- 监视(Watch):可以输入表达式,
len(name_list)来动态查看它的长度。 - 调用栈:看函数是怎么一步步被调用的。
- 逐过程/逐语句:控制执行流程。
提示:如果你还在用记事本或纯文本编辑器写脚本,强烈建议换成支持调试功能的 IDE,学习成本极低,效率提升巨大。
针对特定场景的“急救包”
如果遇到一些棘手的、难以重现的 bug:
-
单元测试(Unit Testing):为你的函数写小测试,这不是调试 bug,而是防止新 bug 引入。
# test_my_function.py import my_module def test_calculate_total(): assert my_module.calculate_total([1, 2, 3]) == 6 -
异常回溯(Traceback):
- Python:
import traceback; traceback.print_exc()会打印完整的错误调用链。 - 通用:在 main 函数外层包裹
try...except捕获所有异常,并打印回溯信息,避免脚本直接退出。
- Python:
-
二分搜索法:如果代码很长,而且不知道哪部分出错了,可以注释掉一半代码,bug 消失了,说明 bug 在被注释的那一半里;然后再注释那一半的一半... 这能快速缩小范围。
调试流程建议
- 遇到 bug 时:先冷静,复现它。
- 使用断言或日志:快速验证你的假设(这里的数据应该是列表”)。
- 插入一个断点(用 IDE 或
ipdb),停在怀疑出错的前面几行。 - 单步执行,观察变量变化,看是哪个逻辑分支走错了。
- 修复问题后,记得写一个测试或断言,确保这个 bug 不会再回来。
通过有意识地练习这些方法,你的调试速度会越来越快,写出的脚本也会更健壮。