Python logging模块详解笔记

一、logging 模块核心组件概述

Python 的 logging 模块提供了一个强大且灵活的日志系统,主要由 LoggerHandlerFormatter 和 Filter 四个核心类组成。用户直接和logger执行交互,具体的处理由Handler完成,实现处理逻辑和用户的调用逻辑实现隔离,用户在调用的时候不用关心日志具体的打印和处理逻辑,Formatter和Filter都作用域Handler,可以用于控制Handler处理的范围和输出的格式。

1. Logger 类

作为日志系统的入口,负责产生日志记录。可设置日志级别,控制整个日志记录流程的初始过滤。使用 logging.getLogger() 创建 Logger 对象。

2. Handler 类

负责将日志记录发送到特定的目标位置,如文件、控制台、邮件等。常见子类有 StreamHandlerFileHandlerSMTPHandler 等。

3. Formatter 类

用于定义日志记录的输出格式,可指定日志信息的显示样式,如时间、日志级别、日志消息等。

4. Filter 类

用于过滤日志记录,只有满足特定条件的日志记录才会被处理。可自定义过滤器,通过继承 Filter 类并重写 filter() 方法实现。

二、日志级别及其作用

logging 模块定义了 5 个标准的日志级别,从低到高分别是 DEBUGINFOWARNINGERROR 和 CRITICAL

1. 各日志级别含义

  • DEBUG(10):用于详细的调试信息,通常在开发和调试阶段使用。
  • INFO(20):记录程序正常运行时的重要信息,帮助管理员了解程序运行状态。
  • WARNING(30):当程序出现可能导致问题但不影响正常运行的情况时使用。
  • ERROR(40):记录程序出现的错误,但程序仍可继续运行。
  • CRITICAL(50):记录导致程序无法继续运行的严重错误。
  • 2. 日志级别设置的影响

    Logger 和 Handler 都可设置日志级别,日志记录需同时满足 Logger 和 Handler 的级别要求才会被处理和输出。例如,当 Logger 级别为 INFO 时,DEBUG 级别的日志记录会被过滤;若 Handler 级别为 WARNING,则只有 WARNING 及以上级别的日志记录会被该 Handler 处理。

    三、Logger 与 Handler 的关系

    1. 一个 Logger 可配备多个 Handler

    一条日志记录产生后,先根据 Logger 的日志级别进行初步过滤,若通过则传递给所有添加到该 Logger 上的 Handler。每个 Handler 再根据自身设置的日志级别和过滤器对日志记录进行进一步过滤,通过过滤的日志记录会被该 Handler 处理并输出到相应目标位置。

    2. 示例代码

    import logging
    
    # 创建 Logger 对象
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    # 创建 StreamHandler 并设置级别
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    
    # 创建 FileHandler 并设置级别
    file_handler = logging.FileHandler('app.log')
    file_handler.setLevel(logging.DEBUG)
    
    # 定义日志格式
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    console_handler.setFormatter(formatter)
    file_handler.setFormatter(formatter)
    
    # 将 Handler 添加到 Logger
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    
    # 记录日志
    logger.debug('这是一条调试级别的日志信息')
    logger.info('这是一条信息级别的日志信息')
    

    四、Handler 与 Filter 的关系

    1. 一个 Handler 可设置多个过滤器

    多个过滤器之间是 “与” 的关系,一条日志记录需依次通过所有过滤器的检查,只有所有过滤器的 filter() 方法都返回 True 时,日志记录才会被 Handler 处理。

    2. 示例代码

    import logging
    
    # 自定义过滤器 1
    class ImportantFilter(logging.Filter):
        def filter(self, record):
            return 'important' in record.getMessage()
    
    # 自定义过滤器 2
    class LengthFilter(logging.Filter):
        def filter(self, record):
            return len(record.getMessage()) > 20
    
    # 创建 Logger 对象
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    # 创建 StreamHandler 对象
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    
    # 为 Handler 添加过滤器
    console_handler.addFilter(ImportantFilter())
    console_handler.addFilter(LengthFilter())
    
    # 将 Handler 添加到 Logger
    logger.addHandler(console_handler)
    
    # 记录日志
    logger.info('This is a short message')
    logger.info('This is an important but short message')
    logger.info('This is an important and long enough message with many details')
    

    五、Formatter 的实现原理

    1. 占位符协议

    Formatter 使用格式字符串来定义日志记录的输出格式,其中包含一些特殊的占位符,如 %(asctime)s%(name)s%(levelname)s 等,这些占位符会被 Formatter 替换为日志记录的实际信息。

    2. 核心方法实现

    Formatter 类的核心方法是 format,其实现步骤如下:

  • 复制日志记录对象的属性到一个字典中。
  • 将日志记录的时间戳转换为本地时间,并格式化日期时间。
  • 使用字符串格式化操作符将格式字符串中的占位符替换为字典中的实际值。
  • 3. 示例代码

    import logging
    
    # 创建 Logger 对象
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.DEBUG)
    
    # 创建 StreamHandler 对象
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.DEBUG)
    
    # 定义日志格式
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s')
    console_handler.setFormatter(formatter)
    
    # 将 Handler 添加到 Logger
    logger.addHandler(console_handler)
    
    # 记录日志
    logger.info('这是一条测试日志')
    

    通过以上组件的配合使用,logging 模块为开发者提供了一个灵活、可定制的日志系统,方便在不同场景下进行日志管理和分析。

    作者:eason再来一次

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python logging模块详解笔记

    发表回复