掘金 人工智能 05月03日 01:24
Python logging 模块基本使用(37)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入介绍了Python的logging模块,该模块为Python程序提供了灵活且强大的日志记录功能。文章从日志记录的重要性出发,概述了logging模块的特点,包括灵活性、层次性和可扩展性。通过详细的示例代码,讲解了如何进行基本的日志记录、设置日志级别、创建和使用日志记录器,以及如何使用不同的日志处理器将日志输出到控制台、文件等位置。此外,还介绍了如何自定义日志格式化,以及如何记录异常信息,帮助开发者全面掌握logging模块的使用方法,从而更好地进行程序调试、监控和审计。

✨ **日志记录的重要性**:日志在调试、监控和审计中扮演关键角色。调试时,日志可帮助定位错误;监控时,可记录系统状态和性能;审计时,可追溯用户操作和系统变化。

🛠️ **logging模块的核心组件**:日志记录器(Logger)负责创建和管理日志,处理器(Handler)将日志发送到不同目标,格式化器(Formatter)定义日志输出格式。通过灵活配置这些组件,可以实现定制化的日志记录。

💾 **多种日志处理器选择**:logging模块提供多种内置处理器,如StreamHandler(控制台输出)、FileHandler(文件输出)、RotatingFileHandler(滚动文件)和TimedRotatingFileHandler(时间滚动文件),满足不同场景的日志存储需求。

🚨 **异常日志记录**:在程序中捕获异常时,可使用logging模块记录异常信息,方便后续调试和排查。这对于快速定位和解决程序中的问题至关重要。

Python logging 模块基本使用

一、引言

在 Python 编程中,日志记录是一项至关重要的功能。无论是开发小型脚本还是大型项目,都需要一种有效的方式来记录程序运行时的信息,比如错误、警告、调试信息等。这些日志信息不仅有助于在程序出现问题时进行调试和排查,还能在程序正常运行时监控程序的状态和性能。Python 的 logging 模块提供了一个灵活且强大的日志记录工具,它允许开发者对日志的输出格式、级别、目标位置等进行细致的控制。本文将深入介绍 logging 模块的基本使用,通过大量的源码示例和详细的注释,帮助你全面掌握该模块的使用方法。

二、logging 模块概述

2.1 日志记录的重要性

日志记录在软件开发中扮演着关键角色,主要体现在以下几个方面:

2.2 logging 模块的特点

Python 的 logging 模块具有以下特点:

三、基本日志记录

3.1 简单的日志记录示例

下面是一个简单的使用 logging 模块进行日志记录的示例:

import logging# 配置日志记录的基本设置# 这里设置日志的级别为 DEBUG,即记录所有级别的日志# 日志的输出格式为包含时间、日志级别和日志消息# 日志将输出到控制台logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')# 记录不同级别的日志logging.debug('This is a debug message')  # 调试信息,通常用于开发过程中的详细信息记录logging.info('This is an info message')  # 一般信息,用于记录程序的正常运行状态logging.warning('This is a warning message')  # 警告信息,提示可能存在的问题,但不影响程序的正常运行logging.error('This is an error message')  # 错误信息,记录程序中出现的错误,但程序可能仍能继续运行logging.critical('This is a critical message')  # 严重错误信息,表明程序可能无法继续运行

在这个示例中,我们首先导入了 logging 模块,然后使用 basicConfig 函数对日志记录进行了基本配置。basicConfig 函数接受多个参数,这里我们设置了日志的级别为 DEBUG,表示记录所有级别的日志;设置了日志的输出格式,包含时间、日志级别和日志消息;日志将输出到控制台。最后,我们使用不同级别的日志记录函数记录了一些日志信息。

3.2 日志级别

logging 模块定义了以下几个日志级别,从低到高依次为:

可以通过 basicConfig 函数的 level 参数来设置日志的级别,只有级别等于或高于该设置的日志才会被记录。例如:

import logging# 配置日志记录的基本设置,将日志级别设置为 INFOlogging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')# 记录不同级别的日志logging.debug('This is a debug message')  # 由于级别低于 INFO,不会被记录logging.info('This is an info message')  # 会被记录logging.warning('This is a warning message')  # 会被记录logging.error('This is an error message')  # 会被记录logging.critical('This is a critical message')  # 会被记录

在这个示例中,我们将日志级别设置为 INFO,因此 DEBUG 级别的日志不会被记录,而 INFOWARNINGERRORCRITICAL 级别的日志会被记录。

四、日志记录器(Logger)

4.1 什么是日志记录器

日志记录器是 logging 模块的核心组件之一,它负责创建和管理日志记录。每个日志记录器都有一个名称,通过名称可以对不同的日志记录器进行区分和管理。日志记录器可以设置自己的日志级别,并且可以添加多个日志处理器(Handler)来控制日志的输出位置。

4.2 创建和使用日志记录器

下面是一个创建和使用日志记录器的示例:

import logging# 创建一个名为 'my_logger' 的日志记录器logger = logging.getLogger('my_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个控制台处理器,用于将日志输出到控制台console_handler = logging.StreamHandler()# 创建一个格式化器,定义日志的输出格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)# 使用日志记录器记录不同级别的日志logger.debug('This is a debug message from my_logger')logger.info('This is an info message from my_logger')logger.warning('This is a warning message from my_logger')logger.error('This is an error message from my_logger')logger.critical('This is a critical message from my_logger')

在这个示例中,我们首先使用 getLogger 函数创建了一个名为 'my_logger' 的日志记录器。然后,我们设置了该日志记录器的级别为 DEBUG。接着,我们创建了一个控制台处理器 StreamHandler,用于将日志输出到控制台。我们还创建了一个格式化器 Formatter,定义了日志的输出格式,并将其添加到控制台处理器中。最后,我们将控制台处理器添加到日志记录器中,并使用日志记录器记录了不同级别的日志。

4.3 日志记录器的层次结构

logging 模块中的日志记录器具有层次结构,根日志记录器是所有日志记录器的父级。可以通过日志记录器的名称来表示其层次关系,例如 'parent.child' 表示 'child''parent' 的子日志记录器。子日志记录器会继承父日志记录器的一些属性,如日志级别和处理器。例如:

import logging# 获取根日志记录器root_logger = logging.getLogger()# 设置根日志记录器的级别为 INFOroot_logger.setLevel(logging.INFO)# 创建一个控制台处理器,用于将日志输出到控制台console_handler = logging.StreamHandler()# 创建一个格式化器,定义日志的输出格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到根日志记录器root_logger.addHandler(console_handler)# 创建一个名为 'parent' 的日志记录器parent_logger = logging.getLogger('parent')# 创建一个名为 'parent.child' 的子日志记录器child_logger = logging.getLogger('parent.child')# 记录日志parent_logger.info('This is an info message from parent_logger')child_logger.info('This is an info message from child_logger')

在这个示例中,我们首先获取了根日志记录器,并设置了其级别为 INFO,同时添加了一个控制台处理器。然后,我们创建了一个名为 'parent' 的日志记录器和一个名为 'parent.child' 的子日志记录器。由于子日志记录器会继承父日志记录器的属性,因此 'parent.child' 日志记录器也会使用根日志记录器的级别和处理器。最后,我们使用这两个日志记录器记录了一些信息日志。

五、日志处理器(Handler)

5.1 什么是日志处理器

日志处理器负责将日志记录发送到不同的目标位置,如控制台、文件、邮件等。logging 模块提供了多种内置的日志处理器,也可以自定义日志处理器。

5.2 常见的日志处理器

5.2.1 控制台处理器(StreamHandler)

控制台处理器用于将日志记录输出到控制台。在前面的示例中,我们已经使用过控制台处理器。下面是一个简单的示例:

import logging# 创建一个日志记录器logger = logging.getLogger('console_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)# 记录日志logger.debug('This is a debug message for console output')
5.2.2 文件处理器(FileHandler)

文件处理器用于将日志记录输出到文件中。下面是一个使用文件处理器的示例:

import logging# 创建一个日志记录器logger = logging.getLogger('file_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个文件处理器,指定日志文件的名称为 'app.log'file_handler = logging.FileHandler('app.log')# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到文件处理器file_handler.setFormatter(formatter)# 将文件处理器添加到日志记录器logger.addHandler(file_handler)# 记录日志logger.debug('This is a debug message for file output')

在这个示例中,我们创建了一个文件处理器 FileHandler,并指定了日志文件的名称为 'app.log'。然后,我们将文件处理器添加到日志记录器中,这样日志就会被记录到 app.log 文件中。

5.2.3 滚动文件处理器(RotatingFileHandler)

滚动文件处理器用于在日志文件达到一定大小时自动进行滚动,即创建新的日志文件,并将旧的日志文件进行备份。下面是一个使用滚动文件处理器的示例:

import loggingfrom logging.handlers import RotatingFileHandler# 创建一个日志记录器logger = logging.getLogger('rotating_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个滚动文件处理器,指定日志文件的名称为 'app_rotating.log'# 最大文件大小为 1024 * 1024 字节(即 1MB),最多保留 5 个备份文件rotating_handler = RotatingFileHandler('app_rotating.log', maxBytes=1024 * 1024, backupCount=5)# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到滚动文件处理器rotating_handler.setFormatter(formatter)# 将滚动文件处理器添加到日志记录器logger.addHandler(rotating_handler)# 循环记录大量日志,触发文件滚动for i in range(10000):    logger.debug(f'This is a debug message {i} for rotating file output')

在这个示例中,我们使用了 RotatingFileHandler 滚动文件处理器,指定了日志文件的名称为 'app_rotating.log',最大文件大小为 1MB,最多保留 5 个备份文件。当日志文件达到 1MB 时,会自动创建一个新的日志文件,并将旧的日志文件进行备份。

5.2.4 时间滚动文件处理器(TimedRotatingFileHandler)

时间滚动文件处理器用于按照时间间隔自动进行日志文件的滚动。下面是一个使用时间滚动文件处理器的示例:

import loggingfrom logging.handlers import TimedRotatingFileHandler# 创建一个日志记录器logger = logging.getLogger('timed_rotating_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个时间滚动文件处理器,指定日志文件的名称为 'app_timed_rotating.log'# 按天进行滚动,即每天创建一个新的日志文件timed_rotating_handler = TimedRotatingFileHandler('app_timed_rotating.log', when='D', interval=1, backupCount=5)# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到时间滚动文件处理器timed_rotating_handler.setFormatter(formatter)# 将时间滚动文件处理器添加到日志记录器logger.addHandler(timed_rotating_handler)# 记录日志logger.debug('This is a debug message for timed rotating file output')

在这个示例中,我们使用了 TimedRotatingFileHandler 时间滚动文件处理器,指定了日志文件的名称为 'app_timed_rotating.log',按天进行滚动,即每天创建一个新的日志文件,最多保留 5 个备份文件。

5.3 为日志记录器添加多个处理器

可以为一个日志记录器添加多个处理器,这样日志就可以同时输出到不同的目标位置。下面是一个示例:

import logging# 创建一个日志记录器logger = logging.getLogger('multi_handler_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个文件处理器,指定日志文件的名称为 'multi_handler.log'file_handler = logging.FileHandler('multi_handler.log')# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器和文件处理器console_handler.setFormatter(formatter)file_handler.setFormatter(formatter)# 将控制台处理器和文件处理器添加到日志记录器logger.addHandler(console_handler)logger.addHandler(file_handler)# 记录日志logger.debug('This is a debug message for multiple handlers')

在这个示例中,我们为日志记录器添加了一个控制台处理器和一个文件处理器,这样日志既会输出到控制台,也会记录到 multi_handler.log 文件中。

六、日志格式化器(Formatter)

6.1 什么是日志格式化器

日志格式化器用于定义日志记录的输出格式。通过使用格式化器,可以控制日志记录中包含的信息,如时间、日志级别、日志消息等。

6.2 基本的日志格式化

logging 模块提供了一些内置的格式化占位符,常用的占位符如下:

下面是一个使用基本格式化占位符的示例:

import logging# 创建一个日志记录器logger = logging.getLogger('formatter_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个格式化器,定义日志的输出格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)# 记录日志logger.debug('This is a formatted debug message')

在这个示例中,我们使用 Formatter 类创建了一个格式化器,定义了日志的输出格式包含时间、日志记录器的名称、日志级别和日志消息。

6.3 自定义日志格式化

除了使用内置的格式化占位符,还可以自定义日志的输出格式。例如,可以使用 datefmt 参数来指定时间的显示格式。下面是一个自定义日志格式化的示例:

import logging# 创建一个日志记录器logger = logging.getLogger('custom_formatter_logger')# 设置日志记录器的级别为 DEBUGlogger.setLevel(logging.DEBUG)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个格式化器,定义日志的输出格式# 使用 datefmt 参数指定时间的显示格式为 '%Y-%m-%d %H:%M:%S'formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)# 记录日志logger.debug('This is a custom formatted debug message')

在这个示例中,我们使用 datefmt 参数指定了时间的显示格式为 '%Y-%m-%d %H:%M:%S',这样日志记录中的时间将以指定的格式显示。

七、异常日志记录

7.1 记录异常信息

在程序中捕获异常时,可以使用 logging 模块记录异常信息,方便后续的调试和排查。下面是一个记录异常信息的示例:

import logging# 创建一个日志记录器logger = logging.getLogger('exception_logger')# 设置日志记录器的级别为 ERRORlogger.setLevel(logging.ERROR)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)try:    # 尝试进行除法运算,故意引发一个除零异常    result = 1 / 0except ZeroDivisionError as e:    # 使用 exception 方法记录异常信息,会自动记录异常的堆栈跟踪信息    logger.exception('An error occurred: %s', e)

在这个示例中,我们使用 try-except 语句捕获了一个除零异常,并使用 logger.exception 方法记录了异常信息。exception 方法会自动记录异常的堆栈跟踪信息,方便我们定位问题。

7.2 记录异常堆栈跟踪信息

除了使用 exception 方法记录异常信息外,还可以使用 exc_info 参数来记录异常的堆栈跟踪信息。下面是一个示例:

import logging# 创建一个日志记录器logger = logging.getLogger('stack_trace_logger')# 设置日志记录器的级别为 ERRORlogger.setLevel(logging.ERROR)# 创建一个控制台处理器console_handler = logging.StreamHandler()# 创建一个格式化器formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')# 将格式化器添加到控制台处理器console_handler.setFormatter(formatter)# 将控制台处理器添加到日志记录器logger.addHandler(console_handler)try:    # 尝试进行除法运算,故意引发一个除零异常    result = 1 / 0except ZeroDivisionError as e:    # 使用 error 方法记录异常信息,并设置 exc_info 参数为 True 以记录堆栈跟踪信息    logger.error('An error occurred: %s', e, exc_info=True)

在这个示例中,我们使用 logger.error 方法记录异常信息,并设置 exc_info 参数为 True,这样会记录异常的堆栈跟踪信息。

八、日志配置

8.1 使用 basicConfig 进行简单配置

在前面的示例中,我们已经使用过 basicConfig 函数进行简单的日志配置。basicConfig 函数可以设置日志的级别、输出格式、目标位置等。下面是一个使用 basicConfig 进行配置的示例:

import logging# 使用 basicConfig 函数进行日志配置# 设置日志级别为 DEBUG# 设置日志输出格式包含时间、日志级别和日志消息# 设置日志输出到文件 'basic_config.log'logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', filename='basic_config.log')# 记录日志logging.debug('This is a debug message configured by basicConfig')

8.2 使用配置文件进行配置

除了使用 basicConfig 函数进行配置外,还可以使用配置文件进行更复杂的日志配置。logging 模块支持使用 fileConfig 函数从配置文件中读取配置信息。下面是一个配置文件 logging.conf 的示例:

[loggers]keys=root,my_logger[handlers]keys=console_handler,file_handler[formatters]keys=simple_formatter[logger_root]level=DEBUGhandlers=console_handler[logger_my_logger]level=DEBUGhandlers=console_handler,file_handlerqualname=my_loggerpropagate=0[handler_console_handler]class=StreamHandlerlevel=DEBUGformatter=simple_formatterargs=(sys.stdout,)[handler_file_handler]class=FileHandlerlevel=DEBUGformatter=simple_formatterargs=('config_file.log',)[formatter_simple_formatter]format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

下面是使用该配置文件进行日志配置的 Python 代码:

import loggingimport logging.config# 从配置文件中读取日志配置信息logging.config.fileConfig('logging.conf')# 获取名为 'my_logger' 的日志记录器logger = logging.getLogger('my_logger')# 记录日志logger.debug('This is a debug message configured by config file')

在这个示例中,我们创建了一个配置文件 logging.conf,在其中定义了日志记录器、处理器和格式化器的配置信息。然后,使用 logging.config.fileConfig 函数从配置文件中读取配置信息,并应用到日志系统中。

8.3 使用字典进行配置

还可以使用字典来配置日志系统,通过 logging.config.dictConfig 函数来应用配置。下面是一个使用字典进行配置的示例:

import loggingimport logging.config# 定义日志配置字典log_config = {    'version': 1,    'disable_existing_loggers': False,    'formatters': {        'simple': {            'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'        }    },    'handlers': {        'console': {            'class': 'logging.StreamHandler',            'level': 'DEBUG',            'formatter': 'simple',            'stream': 'ext://sys.stdout'        },        'file': {            'class': 'logging.FileHandler',            'level': 'DEBUG',            'formatter': 'simple',            'filename': 'dict_config.log'        }    },    'loggers': {        'my_logger': {            'level': 'DEBUG',            'handlers': ['console', 'file'],            'propagate': False        }    },    'root': {        'level': 'DEBUG',        'handlers': ['console']    }}# 应用日志配置字典logging.config.dictConfig(log_config)# 获取名为 'my_logger' 的日志记录器logger = logging.getLogger('my_logger')# 记录日志logger.debug('This is a debug message configured by dictionary')

在这个示例中,我们定义了一个日志配置字典 log_config,其中包含了日志记录器、处理器和格式化器的配置信息。然后,使用 logging.config.dictConfig 函数应用该配置字典。

九、总结与展望

9.1 总结

Python 的 logging 模块为开发者提供了一个强大而灵活的日志记录工具。通过使用日志记录器、处理器、格式化器等组件,可以对日志的输出格式、级别、目标位置等进行细致的控制。可以根据不同的需求选择合适的日志处理器,如控制台处理器、文件处理器、滚动文件处理器等。使用格式化器可以自定义日志的输出格式,方便查看和分析日志信息。在捕获异常时,可以使用 logging 模块记录异常信息和堆栈跟踪信息,有助于调试和排查问题。此外,还可以使用 basicConfig 函数、配置文件或字典来进行日志配置,以满足不同的配置需求。

9.2 展望

随着 Python 在各个领域的广泛应用,日志记录的重要性将更加凸显。未来,logging 模块可能会进一步优化和扩展,提供更多的功能和更好的性能。例如,可能会增加对分布式日志记录的支持,方便在分布式系统中进行日志管理;可能会提供更丰富的日志分析工具,帮助开发者更好地分析和利用日志信息。对于开发者来说,深入理解和掌握 logging 模块的使用方法,合理配置和使用日志记录,将有助于提高程序的可维护性和稳定性。同时,随着日志数据量的不断增加,如何高效地存储、管理和分析日志数据也将成为一个重要的研究方向。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Python logging 日志记录
相关文章