Python技术迷

还只会用 Print() 调试,你就OUT啦!

还只会用 print() 调试?你真的该升级一下调试手段了

上次在公司楼下抽烟,碰到我们组那个小王,他说自己昨晚调一个 Bug,print 了一晚上,结果最后发现是数据库字段拼错了。你说气人不气人?就这种靠 print() 到处插点的方式,现在已经不太适合稍微复杂点的项目了,尤其是多人协作的时候,简直灾难现场。

为什么说 print 不够用了?

你回忆一下啊,debug 的时候你是不是经常写:

print("开始执行接口")
print("参数是:", param)
print("执行结果:", result)

然后上线前再手动删掉,删着删着,还容易把有用的逻辑也删掉,或者漏删一堆无意义输出,搞得控制台像瀑布流一样没法看。更别说你要追踪某个类的方法调用链,那一个 print 根本不顶用啊。

logging 才是基础中的基础

其实吧,Python 官方都告诉你了,别用 print,用 logging!

最简单的写法是这样:

import logging

logging.basicConfig(level=logging.INFO)
logging.info("开始执行接口")

但是你细品这个 logging,它其实比你想象的强太多了,比如你可以设置不同等级:

logging.debug("调试信息")
logging.info("普通信息")
logging.warning("警告")
logging.error("错误")
logging.critical("致命错误")

有些同学调试完忘记调日志等级,结果生产环境日志一堆 debug,运维吐血。你只要设置成 level=logging.WARNING,debug 和 info 就自动不打印了,这不比你到处删 print 高级?

而且你能写多文件输出,能带时间戳、线程名,支持格式化,甚至还能把日志打到远程,比如 ELK 或 Sentry,这在复杂项目里才是真正有用的调试手段。

你知道断点调试有多香吗?

我跟你说个事,我上周调 Flask 的一个奇怪问题,现象是接口有时候直接卡住,但日志什么都没有。print 打了几十个也没看出来原因。后来我直接用了 pdb,几分钟就定位到数据库连接池满了,阻塞了。

pdb 的基本用法其实很简单:

import pdb; pdb.set_trace()

然后你就能在控制台里像 IDE 一样 step、next、continue,还能看变量:

(Pdb) n
(Pdb) p user.name

我甚至建议你直接用 PyCharm 或 VS Code 的断点调试,你点一下行号,加个断点,F5 一下,代码哪一步有问题一清二楚,值是多少、对象结构是啥,都能展开。你再也不用加一堆 print,然后一个个删掉了。

会用装饰器的人,调试效率直接翻倍

你知道我之前怎么排查我们服务某个类方法被频繁调用的吗?我用了一个装饰器,打点计时和输出调用栈,顺便还记录了入参。大概是这样写的:

import time
import traceback

defdebug_decorator(func):
defwrapper(*args, **kwargs):
        print(f"[DEBUG] 调用 {func.__name__},参数: {args}, {kwargs}")
        start = time.time()
        result = func(*args, **kwargs)
        print(f"[DEBUG] {func.__name__} 返回: {result},耗时: {time.time() - start:.3f}s")
        print("调用栈:\n", ''.join(traceback.format_stack(limit=5)))
return result
return wrapper

然后我就在要排查的方法上加一句:

@debug_decorator
defprocess_data(data):
    ...

瞬间我知道它到底被谁调用、执行多久,出了啥结果。这个比你加十个 print 清楚多了吧?

有时候,还得上点黑科技

前几天我实在不想改代码打日志,就用了 sys.settrace 做了个动态函数调用记录器,还有人喜欢用 logging.config 动态切换日志配置,甚至上线环境打日志都不重启服务,靠热加载。你说这些技巧,是不是比 print 那一刀一刀砍出来的方式舒服多了?

你要真进阶一点,还能搞 AOP,或者用 wrapt, aspectlib 那些库,把调试逻辑跟业务彻底解耦——该怎么跑怎么跑,想看日志就加个 hook 就行了,干干净净。

你就记住一句话:print 只能救一时之急,不能当长期饭票。

不信你今晚写段多线程的代码,用 print 去调试,看看它们打印的顺序你能不能搞明白;再试试用 logging 加线程 ID,或者直接用调试器,你就知道我说的是不是实话了。

说多了也没用,你去试试那个 logging 的 RotatingFileHandler,我今天刚用,真香……等会我得先下楼拿个快递回来再继续讲——我还没说完 logging.config 怎么动态加模块日志等级呢。

-END-

我为大家打造了一份RPA教程,完全免费:https://www.songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB,点击下方公众号回复关键字 python 全部免费领