Python日志系统学习路线第12讲_核心原理与实战案例详解【指导】

Python日志系统核心是Logger、Handler、Formatter和Filter四大组件协同:Logger决定“记什么”和“往哪送”,Handler负责“怎么发”和“发给谁”,Formatter定义输出格式,Filter实现精细过滤。

Python日志系统的核心在于理解 logging 模块的四大组件如何协同工作:Logger(记录器)、Handler(处理器)、Formatter(格式器)和 Filter(过滤器)。不搞懂它们之间的关系,配置再复杂也容易出错。

Logger 是入口,决定“记什么”和“往哪送”

每个 Logger 都有日志级别(DEBUG、INFO、WARNING、ERROR、CRITICAL),只有 >= 当前级别的日志才会被处理。Logger 本身不输出日志,而是把日志对象(LogRecord)交给它绑定的 Handler。注意:Logger 可以有多个 Handler,也可以不输出(比如只做转发);子 Logger 默认会向父 Logger 传递日志(propagate=True),这是实现分级控制的关键。

  • logging.getLogger("a.b.c") 获取命名 Logger,推荐按模块名组织,便于统一管理
  • 避免直接用 logging.basicConfig(),它只影响 root Logger,掩盖了层级逻辑
  • 设置 logger.setLevel(logging.DEBUG) 控制本级过滤,但不阻止父级再次过滤

Handler 是出口,决定“怎么发”和“发给谁”

Handler 负责实际的输出动作。常见类型有 StreamHandler(打印到终端)、FileHandler(写入文件)、RotatingFileHandler(自动轮转)、TimedRotatingFileHandler(按时间切分)等。每个 Handler 也可设级别,形成二次过滤。

  • 一个 Handler 只能绑定一个 Formatter,但多个 Handler 可共用同一个 Formatter
  • 生产环境建议至少配两个 Handler:一个输出到文件(带时间轮转),一个输出到 stderr(用于快速排查)
  • 自定义 Handler 很简单——继承 logging.Handler,重写 emit() 方法即可接入 Kafka、ES 或钉钉通知

Formatter 控制“长啥样”,Filter 控制“让不让过”

Formatter 定义日志字符串的结构,支持 %(asctime)s%(name)s%(levelname)s%(message)s 等占位符;Filter 则是更精细的拦截逻辑,可基于 logger 名、消息内容、甚至自定义条件返回 True/False。

  • 推荐在 Formatter 中加入 %(pathname)s:%(lineno)d,方便定位问题代码行
  • Filter 不仅能做白名单(如只放行某个模块的日志),还能动态修改 LogRecord 属性(例如脱敏手机号)
  • Filter 可添加到 Logger 或 Handler 上,作用范围不同:加在 Logger 上影响所有下游 Handler,加在 Handler 上只影响该输出通道

实战案例:一个带分级输出与错误告警的配置

假设项目结构为 app/ 下有 main.pyutils/db.py,要求:
• INFO 及以上写入 daily.log(按天轮转)
• ERROR 及以上同时发邮件(模拟)
• db 模块单独 DEBUG 日志输出到 db_debug.log

  • 创建独立 Logger:db_logger = logging.getLogger("app.utils.db"),设 level=DEBUG
  • 为 db_logger 单独配 FileHandler + DEBUG Formatter,不 propagate 到 root
  • root Logger 配 TimedRotatingFileHandler(level=INFO)和自定义 MailHandler(level=ERROR)
  • MailHandler 中重写 emit(),调用 smtplib 发送摘要(注意异常捕获,避免日志系统崩溃)