Python logging库(python日志库)Logger(记录器、收集器、采集器)、Handler(处理器)、Formatter(格式化器)、Log Level(日志级别)

文章目录

  • Python Logging库详解
  • 简介
  • 日志记录的基本概念
  • 1. Logger(记录器):这是日志系统的入口点。每个记录器都有一个名称,并且记录器之间可以存在父子关系。
  • 2. Handler(处理器):记录器将日志消息发送到处理器,处理器决定如何处理这些消息。常见的处理器有`StreamHandler`、`FileHandler`等。
  • 3. Formatter(格式化器):格式化器定义了日志消息的最终输出格式。
  • 4. Log Level(日志级别):每条日志消息都有一个级别(比如DEBUG、INFO、WARNING、ERROR、CRITICAL),日志系统会根据级别决定是否记录某条消息。
  • 基本用法
  • 代码示例
  • 疑问:为什么代码中有两个 `setLevel(logging.DEBUG)`?
  • 记录器(Logger)
  • 处理器(Handler)
  • 为什么需要两个 `setLevel(logging.DEBUG)`
  • 日志级别
  • 1. DEBUG:详细的信息,通常只在诊断问题时使用。
  • 2. INFO:确认一切按预期工作的信息。
  • 3. WARNING:表示某些意外情况或问题,但不会阻止程序继续运行。
  • 4. ERROR:更严重的问题,表明程序不能执行某些功能。
  • 5. CRITICAL:严重的错误,表明程序可能无法继续运行。
  • 日志配置
  • 基本配置
  • 说明
  • 基本(`logging.basicConfig`,配置日志级别和格式化日期)
  • 简化1(只配置日志级别`level=`)
  • 简化2(什么都不配置,默认日志级别为warning)
  • 高级配置
  • 日志处理器
  • StreamHandler
  • FileHandler
  • 其他处理器
  • `RotatingFileHandler`:用于将日志消息输出到文件,并在文件达到一定大小时进行日志轮换。
  • `TimedRotatingFileHandler`:用于将日志消息输出到文件,并在特定时间间隔进行日志轮换。
  • `SocketHandler`:用于将日志消息发送到网络套接字。
  • `SMTPHandler`:用于通过电子邮件发送日志消息。
  • 日志格式化
  • 基本示例
  • 常用的日志格式化变量
  • 官方文档
  • 常用的日志格式化变量
  • `%(asctime)s`:日志事件发生的时间,格式是可配置的,默认格式为`'YYYY-MM-DD HH:MM:SS,sss'`。(`asc` 是 "ASCII" 的缩写。`asctime` 代表 "ASCII time",即使用ASCII字符表示的时间字符串)
  • `%(levelname)s`:日志级别名称(如`DEBUG`、`INFO`、`WARNING`、`ERROR`、`CRITICAL`)。
  • `%(name)s`:记录器的名称。
  • `%(message)s`:日志消息。
  • `%(filename)s`:调用日志记录函数的源文件的文件名。
  • `%(pathname)s`:调用日志记录函数的源文件的全路径名。
  • `%(module)s`:调用日志记录函数的模块名。
  • `%(funcName)s`:调用日志记录函数的函数名。
  • `%(lineno)d`:调用日志记录函数的语句所在的行号。
  • `%(created)f`:日志事件发生时的时间戳(自UNIX epoch开始的秒数)。
  • `%(msecs)d`:日志事件发生时的毫秒部分。
  • `%(relativeCreated)d`:日志事件发生时相对于Logger创建时间的毫秒数。
  • `%(thread)d`:线程ID。
  • `%(threadName)s`:线程名称。
  • `%(process)d`:进程ID。
  • `%(processName)s`:进程名称。
  • 日志捕捉
  • 基本示例
  • 日志捕捉函数的用法
  • 日志级别函数
  • 1. `logger.debug(msg, *args, **kwargs)`:记录一条DEBUG级别的日志消息。此级别的日志用于详细的信息,通常只在诊断问题时使用。
  • 2. `logger.info(msg, *args, **kwargs)`:记录一条INFO级别的日志消息。此级别的日志用于确认程序按预期工作的信息。
  • 3. `logger.warning(msg, *args, **kwargs)`:记录一条WARNING级别的日志消息。此级别的日志用于指示某些意外情况或问题,但程序仍可以继续运行。
  • 4. `logger.error(msg, *args, **kwargs)`:记录一条ERROR级别的日志消息。此级别的日志用于表示更严重的问题,表明程序不能执行某些功能。
  • 5. `logger.critical(msg, *args, **kwargs)`:记录一条CRITICAL级别的日志消息。此级别的日志用于表示严重的错误,表明程序可能无法继续运行。
  • 日志函数的参数
  • 1. `msg`:这是必需的参数,表示要记录的日志消息。可以是字符串,也可以是包含占位符的字符串,然后通过`*args`或`**kwargs`传入占位符对应的值。
  • 2. `*args`:用于为`msg`中的占位符提供参数。这些参数会以位置参数的形式传递,替换`msg`中的占位符。
  • 3. `**kwargs`:用于为日志消息提供额外的参数,通常用于设置一些可选参数,比如`exc_info`、`stack_info`、`extra`等。
  • 1). `exc_info`:用于记录异常信息。如果设置为`True`,日志消息会包含异常的堆栈信息。这在记录异常时非常有用。
  • 2). `stack_info`:如果设置为`True`,日志消息会包含调用日志函数时的堆栈信息。
  • 3). `extra`:一个字典,用于向日志消息添加额外的信息。这个字典中的键必须是格式化器中使用的占位符。
  • 示例
  • 代码
  • 各日志级别函数及其参数用法解释
  • 1. `logger.debug(msg, *args, **kwargs)`:记录DEBUG级别的日志消息。此级别的日志用于详细的信息,通常只在诊断问题时使用。
  • 2. `logger.info(msg, *args, **kwargs)`:记录INFO级别的日志消息。此级别的日志用于确认程序按预期工作的信息。
  • 3. `logger.warning(msg, *args, **kwargs)`:记录WARNING级别的日志消息。此级别的日志用于指示某些意外情况或问题,但程序仍可以继续运行。
  • 4. `logger.error(msg, *args, **kwargs)`:记录ERROR级别的日志消息。此级别的日志用于表示更严重的问题,表明程序不能执行某些功能。
  • 5. `logger.critical(msg, *args, **kwargs)`:记录CRITICAL级别的日志消息。此级别的日志用于表示严重的错误,表明程序可能无法继续运行。
  • 注意:日志打印中不建议使用`f-string`,建议使用`%惰性格式化`
  • 实际应用中的示例
  • 示例1. 在线电商平台复杂日志系统,包括不同级别和多个输出目标的处理器(Handlers)
  • 完整的日志配置代码示例
  • 解释1
  • 解释2
  • 示例2. 使用过滤器来区分日志内容(logging.Filter)
  • 示例3. 使用python字典配置多个记录器和处理器
  • 总结
  • Python Logging库详解

    在软件开发中,日志是一个不可或缺的部分。它不仅用于调试和错误排查,还可以用于监控应用程序的运行状态。Python提供了一个强大且灵活的日志库——logging,可以满足几乎所有日志记录需求。本文将详细介绍Python的logging库,包括其基本概念、配置方法、日志记录级别、处理器、格式化器,以及如何在实际应用中有效利用它。

    简介

    Python的logging库是标准库的一部分,旨在为应用程序提供灵活的日志记录功能。它可以轻松地记录不同级别的日志信息,并可以将日志信息输出到不同的目标,比如控制台、文件、远程服务器等。logging库非常适合在开发和生产环境中使用,因为它不仅可以帮助开发人员追踪和调试代码,还可以帮助系统管理员监控应用程序的运行状态。

    日志记录的基本概念

    在深入了解logging库的使用之前,需要了解几个基本概念:

    1. Logger(记录器):这是日志系统的入口点。每个记录器都有一个名称,并且记录器之间可以存在父子关系。

    2. Handler(处理器):记录器将日志消息发送到处理器,处理器决定如何处理这些消息。常见的处理器有StreamHandlerFileHandler等。

    3. Formatter(格式化器):格式化器定义了日志消息的最终输出格式。

    4. Log Level(日志级别):每条日志消息都有一个级别(比如DEBUG、INFO、WARNING、ERROR、CRITICAL),日志系统会根据级别决定是否记录某条消息。

    基本用法

    代码示例

    在使用logging库时,首先需要创建一个记录器,然后可以通过这个记录器记录日志消息。下面是一个简单的示例:

    import logging
    
    # 创建一个记录器
    logger = logging.getLogger('my_logger')
    logger.setLevel(logging.DEBUG)
    
    # 创建一个处理器
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    # 创建一个格式化器并将其添加到处理器中
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)
    
    # 将处理器添加到记录器中
    logger.addHandler(ch)
    
    # 记录一些日志消息
    logger.debug('这是一个调试消息')
    logger.info('这是一个信息消息')
    logger.warning('这是一个警告消息')
    logger.error('这是一个错误消息')
    logger.critical('这是一个致命错误消息')
    

    在上述示例中,创建了一个名为my_logger的记录器,并将其日志级别设置为DEBUG。然后创建了一个StreamHandler,用于将日志消息输出到控制台。接着,创建了一个Formatter,定义了日志消息的格式。最后,将处理器和格式化器添加到记录器中,并记录了一些不同级别的日志消息。

    疑问:为什么代码中有两个 setLevel(logging.DEBUG)

    在 Python 的 logging 模块中,有两个 setLevel(logging.DEBUG) 是因为日志记录的级别设置涉及到两个不同的层次:记录器(Logger)和处理器(Handler)。让我们详细讨论一下它们各自的作用和意义。

    记录器(Logger)

    记录器是日志记录的核心,它决定了哪些日志消息会被处理和记录。记录器有一个级别,只有级别高于或等于这个级别的日志消息才会被处理。通过 logger.setLevel(logging.DEBUG),你设置了记录器的最低级别为 DEBUG,这意味着 DEBUG 及其以上级别的消息(DEBUG, INFO, WARNING, ERROR, CRITICAL)都会被处理。

    处理器(Handler)

    处理器是将日志消息发送到合适的输出位置的组件,例如控制台、文件、网络等。每个处理器也有自己的级别设置,只有级别高于或等于处理器级别的日志消息才会被发送到处理器的输出位置。通过 ch.setLevel(logging.DEBUG),你设置了处理器的最低级别为 DEBUG,这意味着 DEBUG 及其以上级别的消息都会被这个处理器处理并输出。

    为什么需要两个 setLevel(logging.DEBUG)
    1. 记录器级别设置:这是为了控制日志消息的初始过滤。只有级别符合条件的消息才会被进一步处理。这一层的设置确保了不必要的日志消息不会浪费资源。

    2. 处理器级别设置:这是为了控制具体的输出行为。即使一条日志消息通过了记录器的级别过滤,如果它的级别低于处理器的级别,它也不会被输出到该处理器。这一层的设置确保了不同的处理器可以有不同的日志输出级别。例如,你可能希望某些重要消息被写入文件,而所有消息都打印到控制台。

    日志级别

    logging库定义了五个标准的日志级别,每个级别都有对应的数值:

    1. DEBUG:详细的信息,通常只在诊断问题时使用。

    2. INFO:确认一切按预期工作的信息。

    3. WARNING:表示某些意外情况或问题,但不会阻止程序继续运行。

    4. ERROR:更严重的问题,表明程序不能执行某些功能。

    5. CRITICAL:严重的错误,表明程序可能无法继续运行。

    使用这些级别可以控制日志的记录和显示。比如,可以设置记录器只记录WARNING及以上级别的日志,而忽略DEBUG和INFO级别的日志。

    日志配置

    基本配置

    说明

    logging.basicConfig() 实际上并没有显式地配置特定的处理器(Handler)。这个 basicConfig 方法在没有提供其他参数的情况下,会默认配置一个 StreamHandler,它将日志输出到标准输出(通常是控制台)。这个默认的设置等同于创建了一个很基本的控制台日志处理器。

    这里的 StreamHandler 是最简单的日志处理器之一,用于将日志消息发送到控制台。它会接收所有等于或高于它配置级别的日志消息(代码中为 DEBUG 级别),并将其输出到 sys.stdout,即 Python 程序的标准输出。

    基本(logging.basicConfig,配置日志级别和格式化日期)

    logging库提供了一个简单的配置函数logging.basicConfig,可以用来快速配置日志系统。下面是一个基本配置的示例:

    import logging
    
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    
    logging.debug('这是一个调试消息')
    logging.info('这是一个信息消息')
    logging.warning('这是一个警告消息')
    logging.error('这是一个错误消息')
    logging.critical('这是一个致命错误消息')
    

    在上述示例中,使用basicConfig函数设置了日志级别和日志格式。所有日志消息将输出到控制台,并且使用指定的格式。

    简化1(只配置日志级别level=
    import logging
    
    logging.basicConfig(level=logging.DEBUG)
    
    logging.debug('这是一个调试消息')
    logging.info('这是一个信息消息')
    logging.warning('这是一个警告消息')
    logging.error('这是一个错误消息')
    logging.critical('这是一个致命错误消息')
    
    

    简化2(什么都不配置,默认日志级别为warning)
    import logging
    
    logging.basicConfig()
    
    logging.debug('这是一个调试消息')
    logging.info('这是一个信息消息')
    logging.warning('这是一个警告消息')
    logging.error('这是一个错误消息')
    logging.critical('这是一个致命错误消息')
    
    

    高级配置

    对于更复杂的日志需求,可以使用字典配置或配置文件来配置日志系统。以下是使用字典配置的示例:

    import logging
    import logging.config
    
    log_config = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'standard': {
                'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s',
            },
        },
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
                'formatter': 'standard',
                'level': logging.DEBUG,
            },
            'file': {
                'class': 'logging.FileHandler',
                'filename': 'app.log',
                'formatter': 'standard',
                'level': logging.DEBUG,
            },
        },
        'loggers': {
            '': {
                'handlers': ['console', 'file'],
                'level': logging.DEBUG,
                'propagate': True,
            },
        }
    }
    
    logging.config.dictConfig(log_config)
    
    logger = logging.getLogger(__name__)
    
    logger.debug('这是一个调试消息')
    logger.info('这是一个信息消息')
    logger.warning('这是一个警告消息')
    logger.error('这是一个错误消息')
    logger.critical('这是一个致命错误消息')
    
    


    在上述示例中,使用字典配置了日志系统,包括格式化器、处理器和记录器。日志消息将同时输出到控制台和文件app.log

    日志处理器

    日志处理器是日志系统中负责将日志消息发送到不同目标的组件。logging库提供了多种处理器,包括StreamHandlerFileHandler等。

    StreamHandler

    StreamHandler用于将日志消息输出到流(如控制台、文件等)。下面是一个使用StreamHandler的示例:

    import logging
    
    logger = logging.getLogger('my_logger')
    logger.setLevel(logging.DEBUG)
    
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)
    
    logger.addHandler(ch)
    
    logger.debug('这是一个调试消息')
    

    FileHandler

    FileHandler用于将日志消息输出到文件。下面是一个使用FileHandler的示例:

    import logging
    
    logger = logging.getLogger('my_logger')
    logger.setLevel(logging.DEBUG)
    
    fh = logging.FileHandler('my_log.log')
    fh.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    fh.setFormatter(formatter)
    
    logger.addHandler(fh)
    
    logger.debug('这是一个调试消息')
    

    其他处理器

    除了StreamHandlerFileHandlerlogging库还提供了其他多种处理器,比如:

    RotatingFileHandler:用于将日志消息输出到文件,并在文件达到一定大小时进行日志轮换。
    TimedRotatingFileHandler:用于将日志消息输出到文件,并在特定时间间隔进行日志轮换。
    SocketHandler:用于将日志消息发送到网络套接字。
    SMTPHandler:用于通过电子邮件发送日志消息。

    日志格式化

    基本示例

    日志格式化器用于定义日志消息的输出格式。logging库的Formatter类允许使用格式字符串自定义日志消息的格式。下面是一个示例:

    import logging
    
    logger = logging.getLogger('my_logger')
    logger.setLevel(logging.DEBUG)
    
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)
    
    logger.addHandler(ch)
    
    logger.debug('这是一个调试消息')
    

    在上述示例中,使用格式字符串'%(asctime)s - %(name)s - %(levelname)s - %(message)s'定义了日志消息的格式,包括时间戳、记录器名称、日志级别和消息内容。

    常用的日志格式化变量

    在Python的logging模块中,日志格式化字符串可以包含多个特定的变量,这些变量会在日志记录时被自动替换。除了你提到的%(asctime)s%(name)s%(levelname)s%(message)s,还有许多其他的变量可以使用。

    官方文档

    可以在官方文档中找到所有可用的格式化变量:

  • Logging Module Documentation
  • 常用的日志格式化变量
    %(asctime)s:日志事件发生的时间,格式是可配置的,默认格式为'YYYY-MM-DD HH:MM:SS,sss'。(asc 是 “ASCII” 的缩写。asctime 代表 “ASCII time”,即使用ASCII字符表示的时间字符串)
    %(levelname)s:日志级别名称(如DEBUGINFOWARNINGERRORCRITICAL)。
    %(name)s:记录器的名称。
    %(message)s:日志消息。
    %(filename)s:调用日志记录函数的源文件的文件名。
    %(pathname)s:调用日志记录函数的源文件的全路径名。
    %(module)s:调用日志记录函数的模块名。
    %(funcName)s:调用日志记录函数的函数名。
    %(lineno)d:调用日志记录函数的语句所在的行号。
    %(created)f:日志事件发生时的时间戳(自UNIX epoch开始的秒数)。
    %(msecs)d:日志事件发生时的毫秒部分。
    %(relativeCreated)d:日志事件发生时相对于Logger创建时间的毫秒数。
    %(thread)d:线程ID。
    %(threadName)s:线程名称。
    %(process)d:进程ID。
    %(processName)s:进程名称。

    日志捕捉

    基本示例

    在开发过程中,有时需要捕捉代码中的异常并记录日志。logging库提供了便捷的方式来实现这一功能。下面是一个示例:

    import logging
    
    logger = logging.getLogger('my_logger')
    logger.setLevel(logging.DEBUG)
    
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    ch.setFormatter(formatter)
    
    logger.addHandler(ch)
    
    try:
        1 / 0
    except ZeroDivisionError as e:
        logger.error('捕捉到异常', exc_info=True)
    

    在上述示例中,捕捉到ZeroDivisionError异常,并使用logger.error记录了异常信息。exc_info=True参数确保异常的堆栈信息也被记录下来。

    日志捕捉函数的用法

    logging库中,每个日志级别都有一个对应的函数,用于记录该级别的日志消息。这些函数包括debuginfowarningerrorcritical。每个函数的用法基本相同,但它们的日志级别不同,使用时需要根据具体的日志需求选择合适的函数。

    日志级别函数
    1. logger.debug(msg, *args, **kwargs):记录一条DEBUG级别的日志消息。此级别的日志用于详细的信息,通常只在诊断问题时使用。
    2. logger.info(msg, *args, **kwargs):记录一条INFO级别的日志消息。此级别的日志用于确认程序按预期工作的信息。
    3. logger.warning(msg, *args, **kwargs):记录一条WARNING级别的日志消息。此级别的日志用于指示某些意外情况或问题,但程序仍可以继续运行。
    4. logger.error(msg, *args, **kwargs):记录一条ERROR级别的日志消息。此级别的日志用于表示更严重的问题,表明程序不能执行某些功能。
    5. logger.critical(msg, *args, **kwargs):记录一条CRITICAL级别的日志消息。此级别的日志用于表示严重的错误,表明程序可能无法继续运行。
    日志函数的参数

    每个日志级别函数都可以接受以下参数:

    1. msg:这是必需的参数,表示要记录的日志消息。可以是字符串,也可以是包含占位符的字符串,然后通过*args**kwargs传入占位符对应的值。
    2. *args:用于为msg中的占位符提供参数。这些参数会以位置参数的形式传递,替换msg中的占位符。
    3. **kwargs:用于为日志消息提供额外的参数,通常用于设置一些可选参数,比如exc_infostack_infoextra等。
    1). exc_info:用于记录异常信息。如果设置为True,日志消息会包含异常的堆栈信息。这在记录异常时非常有用。
    2). stack_info:如果设置为True,日志消息会包含调用日志函数时的堆栈信息。
    3). extra:一个字典,用于向日志消息添加额外的信息。这个字典中的键必须是格式化器中使用的占位符。

    就是说格式化器中出现的字段,日志捕获函数参数中必须提供,如:

    # 创建格式化器
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(user_defined_info)s')
    # 定义额外的参数
    extra_info = {'user_defined_info': 'xxxxxxx'}
    # 记录CRITICAL级别的日志,并使用堆栈信息
    logger.critical('这是一个致命错误消息', stack_info=True, extra=extra_info)
    

    如果执行logger.critical函数extra参数中的字典没有提供相应字段的信息,就会报错。

    示例代码:

    import logging
    
    # 创建记录器
    logger = logging.getLogger('example_logger')
    logger.setLevel(logging.DEBUG)
    
    # 创建处理器并设置级别
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    # 创建格式化器
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(user_defined_info)s')
    ch.setFormatter(formatter)
    
    # 将处理器添加到记录器
    logger.addHandler(ch)
    
    # 定义额外的参数
    extra_info = {'user_defined_info': 'xxxxxxxxx'}
    
    # 记录DEBUG级别的日志
    logger.debug('这是一个调试消息', extra=extra_info)
    
    

    示例
    代码
    import logging
    
    # 创建记录器
    logger = logging.getLogger('example_logger')
    logger.setLevel(logging.DEBUG)
    
    # 创建处理器并设置级别
    ch = logging.StreamHandler()
    ch.setLevel(logging.DEBUG)
    
    # 创建格式化器
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(user)s')
    ch.setFormatter(formatter)
    
    # 将处理器添加到记录器
    logger.addHandler(ch)
    
    # 定义额外的参数
    extra_info = {'user': 'admin'}
    
    # 记录DEBUG级别的日志
    logger.debug('这是一个调试消息', extra=extra_info)
    
    # 记录INFO级别的日志
    logger.info('这是一个信息消息', extra=extra_info)
    
    # 记录WARNING级别的日志,并使用位置参数
    logger.warning('这是一个警告消息,参数1: %s, 参数2: %d', 'param1', 2, extra=extra_info)
    
    # 记录ERROR级别的日志,并包含异常信息
    try:
        1 / 0
    except ZeroDivisionError as e:
        logger.error('捕捉到异常', exc_info=True, extra=extra_info)
    
    # 记录CRITICAL级别的日志,并使用堆栈信息
    logger.critical('这是一个致命错误消息', stack_info=True, extra=extra_info)
    
    

    各日志级别函数及其参数用法解释
    1. logger.debug(msg, *args, **kwargs):记录DEBUG级别的日志消息。此级别的日志用于详细的信息,通常只在诊断问题时使用。

    示例:

    logger.debug('这是一个调试消息', extra=extra_info)
    
    2. logger.info(msg, *args, **kwargs):记录INFO级别的日志消息。此级别的日志用于确认程序按预期工作的信息。

    示例:

    logger.info('这是一个信息消息', extra=extra_info)
    
    3. logger.warning(msg, *args, **kwargs):记录WARNING级别的日志消息。此级别的日志用于指示某些意外情况或问题,但程序仍可以继续运行。

    示例:

    logger.warning('这是一个警告消息,参数1: %s, 参数2: %d', 'param1', 2, extra=extra_info)
    
    4. logger.error(msg, *args, **kwargs):记录ERROR级别的日志消息。此级别的日志用于表示更严重的问题,表明程序不能执行某些功能。

    示例:

    try:
        1 / 0
    except ZeroDivisionError as e:
        logger.error('捕捉到异常', exc_info=True, extra=extra_info)
    
    5. logger.critical(msg, *args, **kwargs):记录CRITICAL级别的日志消息。此级别的日志用于表示严重的错误,表明程序可能无法继续运行。

    示例:

    logger.critical('这是一个致命错误消息', stack_info=True, extra=extra_info)
    

    注意:日志打印中不建议使用f-string,建议使用%惰性格式化

    参考文章:python fstring教程(f-string教程)(python3.6+格式化字符串方法)(%惰性格式化%)

    实际应用中的示例

    示例1. 在线电商平台复杂日志系统,包括不同级别和多个输出目标的处理器(Handlers)

    根据你提供的需求和配置,我将给出一个示例代码,展示如何为一个大型的在线电商平台配置一个复杂的日志系统,包括不同级别和多个输出目标的处理器(Handlers)。

    完整的日志配置代码示例
    import logging
    import sys
    
    
    def setup_logging():
        # 创建一个名为 'ecommerce' 的全局 Logger
        logger_ = logging.getLogger('ecommerce')
        logger_.setLevel(logging.DEBUG)  # 设置 Logger 的级别为 DEBUG
    
        # 创建文件 Handler 1:用于操作日志,记录级别为 INFO
        file_handler_info = logging.FileHandler('operations.log')
        file_handler_info.setLevel(logging.INFO)
        file_handler_info.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        # 创建文件 Handler 2:用于错误报告,记录级别为 ERROR
        file_handler_error = logging.FileHandler('errors.log')
        file_handler_error.setLevel(logging.ERROR)
        file_handler_error.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        # 创建控制台 Handler:用于调试信息,记录级别为 DEBUG
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        # 创建性能监控 Handler:用于性能监控日志,记录级别为 INFO
        performance_handler = logging.FileHandler('performance.log')
        performance_handler.setLevel(logging.INFO)
        performance_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        # 将所有 Handler 添加到 Logger
        logger_.addHandler(file_handler_info)
        logger_.addHandler(file_handler_error)
        logger_.addHandler(console_handler)
        logger_.addHandler(performance_handler)
    
        return logger_
    
    
    # 配置并获取 Logger
    logger = setup_logging()
    
    # 使用 Logger 记录一些示例消息
    logger.debug('Debug message: User session started')
    logger.info('Info message: User logged in')
    logger.warning('Warning message: User session timeout is approaching')
    logger.error('Error message: Failed to process transaction')
    logger.critical('Critical message: System is down')
    
    
    


    解释1
  • 这个配置设置了一个全局的 Logger ecommerce,它有四个不同的 Handler,每个 Handler 都设置了不同的日志级别和输出目标。
  • file_handler_infofile_handler_error 分别用于操作日志和错误报告,记录不同级别的日志到不同的文件中。
  • console_handler 用于在开发过程中在控制台输出调试信息。
  • performance_handler 用于记录与性能相关的关键信息。
  • 这样的配置确保日志信息根据其重要性和用途被适当地分流和存储,从而提高了系统的可维护性和监控能力。

    解释2

    代码中名为 ecommerce的全局 Logger(记录器),设置级别为 DEBUG,这意味着DEBUG级别及以上的日志消息会被记录;

    file_handler_info处理器设置级别为INFO,意味着会处理INFO级别及以上的日志消息;
    同理,其他处理器也会处理其设置的级别及以上的日志消息;

    示例2. 使用过滤器来区分日志内容(logging.Filter)

    下面是一个使用过滤器来区分日志内容的示例:

    import logging
    import sys
    
    
    class PerformanceFilter(logging.Filter):
        def filter(self, record):
            # 打印调试信息以确认过滤器是否被触发
            contains_performance = 'Performance' in record.getMessage()
            print(f"Filtering: {record.getMessage()}, Result: {contains_performance}")
            return contains_performance
    
    
    def setup_logging():
        logger = logging.getLogger('ecommerce')
        logger.setLevel(logging.DEBUG)
    
        file_handler_info = logging.FileHandler('operations.log')
        file_handler_info.setLevel(logging.DEBUG)
        file_handler_info.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        console_handler = logging.StreamHandler(sys.stdout)
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
    
        performance_handler = logging.FileHandler('performance.log')
        performance_handler.setLevel(logging.DEBUG)
        performance_handler.setFormatter(logging.Formatter(
            '%(asctime)s - %(levelname)s - %(message)s'))
        performance_handler.addFilter(
            PerformanceFilter())  # 只记录包含'performance'的日志消息
    
        logger.addHandler(file_handler_info)
        logger.addHandler(console_handler)
        logger.addHandler(performance_handler)
    
        return logger
    
    
    logger = setup_logging()
    logger.debug('User logged in')  # 不会记录到 performance.log
    logger.debug('Performance metrics: CPU usage at 70%')  # 会记录到 performance.log
    
    

    在这个例子中,PerformanceFilter 过滤器将检查日志消息是否包含 ‘Performance’ 这个关键字,如果包含,则这些日志消息会被记录到 performance.log 文件中,而不是 operations.log。这样可以有效地将日志内容区分开来,确保每个文件只包含相关的信息。

    注意:python in语法判断字符串中是否包含字串是匹配大小写的。

    示例3. 使用python字典配置多个记录器和处理器

    在实际应用中,日志系统通常会根据应用的需求进行配置和使用。下面是一个更复杂的示例,展示了如何在实际应用中配置和使用logging库:

    import logging
    import logging.config
    
    log_config = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'detailed': {
                'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s - %(pathname)s:%(lineno)d',
            },
            'simple': {
                'format': '%(asctime)s - %(levelname)s - %(message)s',
            },
        },
        'handlers': {
            'console': {
                'class': 'logging.StreamHandler',
                'formatter': 'simple',
                'level': logging.DEBUG,
            },
            'file': {
                'class': 'logging.FileHandler',
                'filename': 'app.log',
                'formatter': 'detailed',
                'level': logging.DEBUG,
            },
            'error_file': {
                'class': 'logging.FileHandler',
                'filename': 'errors.log',
                'formatter': 'detailed',
                'level': logging.ERROR,
            },
        },
        'loggers': {
            '': {
                'handlers': ['console', 'file'],
                'level': logging.DEBUG,
                'propagate': True,
            },
            'error_logger': {
                'handlers': ['error_file'],
                'level': logging.ERROR,
                'propagate': False,
            },
        }
    }
    
    logging.config.dictConfig(log_config)
    
    logger = logging.getLogger('app_logger')
    error_logger = logging.getLogger('error_logger')
    
    logger.debug('这是一个调试消息')
    logger.info('这是一个信息消息')
    logger.warning('这是一个警告消息')
    logger.error('这是一个错误消息')
    logger.critical('这是一个致命错误消息')
    
    try:
        1 / 0
    except ZeroDivisionError as e:
        error_logger.error('捕捉到异常', exc_info=True)
    

    在这个示例中,配置了多个格式化器、处理器和记录器。普通日志消息输出到控制台和app.log文件,而错误日志消息还会额外输出到errors.log文件。这样,可以在实际应用中根据不同的需求记录和管理日志。

    总结

    本文详细介绍了Python的logging库,从基本概念、基本用法到高级配置和实际应用。通过logging库,开发者可以灵活地记录和管理日志,帮助调试和监控应用程序。掌握logging库的使用方法,是每个Python开发者必备的技能。

    作者:Dontla

    物联沃分享整理
    物联沃-IOTWORD物联网 » Python logging库(python日志库)Logger(记录器、收集器、采集器)、Handler(处理器)、Formatter(格式化器)、Log Level(日志级别)

    发表回复