Python 日志

logging 模块分层:logger/handler/formatter;用级别与上下文支撑运维,而不是 print。

#type / concept #status / growing #tech / dev #resource / python #tech / lang / python

[!info] 关联笔记

Python 日志

这个概念为什么出现

print 无法分级、无法统一格式、难以在库中关闭。logging 提供可配置的诊断通道。

[!abstract] 一句话理解 业务代码拿 logger 打点;handler 决定输出到哪,formatter 决定长什么样,级别控制噪声。

最小可运行示例

先把示例放进业务场景,再看代码:

场景:下单路径记录 info 与错误

# order_logging_demo.py
# 业务意图:用标准 logging 记录下单成功/失败。
# 教学点:
# - getLogger;
# - basicConfig;
# - 异常日志。

import logging

logger = logging.getLogger("billing.order")


def place_order(user_id: str, ok: bool) -> None:
    logger.info("placing order user=%s", user_id)
    if not ok:
        try:
            raise RuntimeError("payment declined")
        except RuntimeError:
            logger.exception("order failed user=%s", user_id)
            raise
    logger.info("order ok user=%s", user_id)


def main() -> None:
    logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s: %(message)s")
    place_order("u1", True)
    try:
        place_order("u2", False)
    except RuntimeError:
        pass


if __name__ == "__main__":
    main()

建议运行:

python order_logging_demo.py

期望输出(含 traceback 片段):

INFO billing.order: placing order user=u1
INFO billing.order: order ok user=u1
INFO billing.order: placing order user=u2
ERROR billing.order: order failed user=u2
Traceback (most recent call last):
...
RuntimeError: payment declined

结合场景再看三个关注点

  1. 库用 getLogger(name),应用配置 handler。
  2. exception 带堆栈。
  3. 结构化字段(JSON logs)在生产更易检索。

核心概念与准确模型

  • Logger → Handler → Formatter
  • 级别:DEBUG/INFO/WARNING/ERROR/CRITICAL
  • 传播 propagate
  • 过滤器 Filter

边界情况与反直觉行为

  1. 未配置时 “最后手段” handler 行为。
  2. 多进程日志 文件写入要小心。
  3. 敏感数据 脱敏。

常见误区

[!warning] 常见误区:库里 basicConfig 错误理解:方便。
正确模型:库只打点,应用配置。

工程实践

  • 请求 ID 写入上下文
  • 级别可动态调
  • 与指标/追踪关联

本节总结

日志是运行时叙事。设计字段与级别,比堆 print 重要。

自测题

  1. 为何用 %s 惰性格式化?
  2. 库为何不 basicConfig?
参考答案
  1. 未启用该级别时可避免格式化开销(经典建议)。
  2. 避免抢占应用的全局日志策略。

延伸阅读与资料来源

资料类型支撑内容
logging文档标准库
Logging HOWTOHOWTO实践
创建于 2026/7/15 更新于 2026/7/15