一、核心组件与类图
logging
模块的核心组件包括 Logger、Handler、Filter、Formatter 和 LogRecord。它们的关系如下:
1. Logger(日志记录器)
- 作用:应用程序调用的接口,负责生成日志并传递到处理器(Handler)。
- 源码关键点:
- 继承自
Filterer
,支持过滤器链。 - 通过
getLogger(name)
获取实例,支持层级结构(如parent.child
继承父级配置)。 - 核心方法:
debug()
、info()
、warning()
等,最终调用_log()
方法生成LogRecord
。
- 继承自
2. Handler(处理器)
- 作用:决定日志的输出位置(如文件、控制台、网络)。
- 子类示例:
StreamHandler
:输出到流(如sys.stderr
)。FileHandler
:输出到文件。RotatingFileHandler
:按文件大小滚动日志。
- 源码关键点:
- 继承自
Filterer
,每个 Handler 可独立设置级别和过滤器。 - 核心方法
emit(record)
由子类实现具体输出逻辑。
- 继承自
3. Formatter(格式器)
- 作用:定义日志的输出格式(如时间、级别、消息)。
- 源码关键点:
- 使用
format
字符串模板(如%(asctime)s - %(message)s
)。 LogRecord
的__dict__
属性提供格式化字段数据。
- 使用
4. LogRecord(日志记录)
- 作用:封装单条日志的元数据(如时间、级别、文件名、行号)。
- 源码关键点:
- 由
Logger.makeRecord()
创建,包含日志的所有上下文信息。 - 通过
getMessage()
方法生成最终消息。
- 由
5. Filter(过滤器)
- 作用:提供细粒度日志过滤(如按模块名或关键字过滤)。
- 源码关键点:
filter(record)
方法返回True
则允许日志通过。
二、关键流程与源码分析
1. 日志记录流程
- 日志调用:用户调用
logger.info(msg)
。 - 级别检查:
Logger.isEnabledFor(level)
判断是否记录该级别日志。 - 创建 LogRecord:调用
Logger._log()
生成LogRecord
对象,包含调用栈信息(如文件名、行号)。 - 处理过滤器:依次通过
Logger
和Handler
的过滤器链。 - 处理器分发:将
LogRecord
传递给所有关联的Handler
。 - 格式与输出:
Handler
使用Formatter
格式化日志并输出(如写入文件)。
2. 线程安全机制
- 锁机制:通过
_acquireLock()
和_releaseLock()
使用threading.RLock
保证线程安全(如配置basicConfig
时)。 - 示例代码:
def basicConfig(**kwargs): _acquireLock() try: # 配置逻辑 finally: _releaseLock()
3. 日志传播与层级结构
- 传播机制:子 Logger 默认将日志传递给父 Logger(通过
Logger.propagate
控制)。 - 层级命名:
getLogger('a.b')
会继承a
的配置,最终传递到根 Logger(root
)。
4. 异常处理
- 记录堆栈:通过
logger.exception()
或_log()
的exc_info
参数捕获异常堆栈。 - 源码片段:
def _log(self, level, msg, args, exc_info=None): if exc_info: exc_info = sys.exc_info() # 捕获当前异常 record = self.makeRecord(..., exc_info=exc_info) self.handle(record)
三、核心源码解析
1. Logger 类
-
初始化:
class Logger(Filterer): def __init__(self, name, level=NOTSET): self.name = name self.level = _checkLevel(level) self.handlers = [] self.propagate = True # 默认传播到父 Logger
-
日志生成:
def info(self, msg, *args, **kwargs): if self.isEnabledFor(INFO): self._log(INFO, msg, args, **kwargs)
2. Handler 类
- 输出逻辑:
class StreamHandler(Handler): def emit(self, record): try: msg = self.format(record) self.stream.write(msg + self.terminator) except Exception: self.handleError(record)
3. LogRecord 类
- 记录元数据:
class LogRecord(object): def __init__(self, name, level, pathname, lineno, msg, args, exc_info, func=None): self.name = name self.levelname = getLevelName(level) self.msg = msg # 其他字段如 asctime、filename 等
四、设计模式与扩展性
- 责任链模式:日志从 Logger 到 Handler 的传递过程。
- 单例模式:根 Logger(
root
)全局唯一,通过getLogger()
管理实例。 - 扩展性:可通过自定义
Handler
和Filter
实现复杂需求(如日志发送到 Kafka)。
五、性能优化建议
- 避免高频 DEBUG 日志:通过
logger.isEnabledFor(DEBUG)
提前判断。 - 异步日志:使用
QueueHandler
和QueueListener
分离 I/O 操作。 - 合理配置层级:减少不必要的日志传播。
总结
logging
模块通过 Logger-Handler-Filter-Formatter 的架构实现灵活的日志管理,源码中通过线程锁、层级传播和丰富的扩展点保证了其高效性与可定制性。深入理解其设计,可帮助开发者优化日志配置并解决复杂场景下的问题。