上周五下午五点半,老板路过我工位,扔下一句“那个数据报表的bug今天得修好”。我看了眼代码,头皮发麻。两百多行脚本跑出来全是乱码,测试同事已经在群里@我三次了。结果我只改了两行代码,问题就解决了。六点零二分,我准时关了电脑。
这种事发生过太多次了。Python调试有时候真的让人抓狂,尤其是那种找了半天发现是少了个冒号的问题。我把自己常用的5个调试技巧整理了一下,都是平时真能用上的。
1. print大法加上个“身份牌”
大部分人调试就写个 print('111') 或者 print('到这里了')。但代码跑起来,满屏都是111,根本分不清谁是谁。我习惯改成 print(f'[函数A-第42行] 变量值:{my_var}')。这样一眼就知道代码跑到哪了,变量是什么值。比干巴巴的print好用十倍。
3. 用logging代替print
print的缺点是上线前得删掉,不然线上环境会被刷屏。我后来改用 logging.debug('正在处理第%s条记录', index)。设置个日志级别,开发时全看,上线只保留警告和错误。不用删代码,不会影响性能。这个习惯帮我省了很多重复劳动。
4. 断点调试别只用IDE的图形界面
很多人点IDE上的小虫子图标开始调试,但遇到多进程或者线上环境就用不了。我推荐用内置的 pdb。在代码里加一行 import pdb; pdb.set_trace(),跑起来就会停住。用命令 n 下一步,p 变量名 看值,c 继续。这个方法在服务器上也能用,不用装任何额外东西。
5. 用assert锁死不可能的情况
有时候代码逻辑很复杂,一个函数返回的结果你不确定是不是对的。我会加 assert 0 <= score <= 100, f'分数异常:{score}'。如果分数跑出范围,程序立刻报错。这比事后检查快得多。我那个月的一个bug,就是因为分页函数里传了个负数页码,用assert一秒就定位了。
2. 异常别只抓Exception
很多人写代码就是 try: ... except: pass。等于把错误吞了。正确的做法是至少写成 try: ... except Exception as e: print(e)。更专业一点,用 traceback.print_exc() 打印完整的调用栈。你看过那种灰色背景的五颜六色的错误堆栈吗?那个信息量比只打印“list index out of range”多一百倍。
这五个技巧我每天都在用。真的,很多时候bug不是复杂,是你找不到它在哪。把工具用对了,两行代码就能解决问题。不用加班,不用焦虑。收藏起来,下次遇到奇怪的问题,先试试这些东西。
最后说一句,调试不要靠猜。靠工具,靠日志,靠断言。这比拍脑袋改代码靠谱多了。