日志性能损耗主要来自参数求值、格式化、时间戳获取和栈帧解析。DEBUG级别下即使不输出,参数仍会执行;应使用isEnabledFor或延迟计算;basicConfig默认配置不适用于生产;高频日志需限流;%(pathname)s等字段性能差;异步环境中需防丢日志。

Python 日志打印对性能的真实影响

日志级别设为 DEBUG 时,字符串拼接本身就会拖慢程序

很多同学以为“只要没输出,日志就不耗性能”,其实不对。Python 的 logging.debug() 在调用时,哪怕日志器最终丢弃这条消息(因为级别不够),debug() 的参数仍会照常求值——包括字符串格式化、函数调用、变量访问。比如:

logging.debug("user_id=%s, balance=%.2f", user.id, get_balance(user))

即使当前日志级别是 WARNINGuser.idget_balance(user) 依然会被执行。

logging.basicConfig() 的默认行为在生产环境几乎总是错的

本地调试时随手加一句 logging.basicConfig(level=logging.INFO) 很方便,但它会悄悄创建一个 StreamHandler 绑定到 root logger,并且没有设置 formatterfilter。上线后问题就来了:

线上应该显式配置 handler,比如:

handler = logging.FileHandler("/var/log/app.log")
handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s"))
logger.addHandler(handler)
logger.setLevel(logging.INFO)
logger.propagate = False

频繁调用 logger.info() 但内容不变,CPU 花在哪儿了?

看起来只是打一行固定字符串,比如 logger.info("request started"),但每次调用仍要走完整路径:检查级别 → 获取线程/进程 ID → 获取时间戳 → 格式化 → 编码 → 写入 buffer。其中最重的是时间戳获取和 formatter 调用。

异步框架(如 FastAPI / Quart)里用标准 logging 不会阻塞,但可能丢日志

标准 logging 是同步的,但在 asyncio 场景下,它不会阻塞 event loop——因为写文件或 socket 是系统调用,Python 的 logging 模块本身不主动 await。真正的问题是生命周期错配:

最常被忽略的一点:日志不是越全越好,而是要在可追溯性和性能损耗之间做显式取舍。比如 trace_id 可以用 extra 传入,但别每次都在 formatter 里调用 trace.get_current_span() —— 那个函数本身就要查上下文、加锁、生成新对象。

本文转载于:互联网 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。