概述

在上一节,我们介绍了Python的collections模块,包括:collections模块中一些常用的函数和类。在这一节,我们将介绍Python的logging模块。logging模块是一个用于记录和调试的标准库,它提供了一种灵活的方式来记录不同级别的消息,比如:调试信息、错误信息、警告信息等。这个模块非常有用,因为它可以帮助开发者理解应用程序在运行时到底发生了什么。当程序出现错误或异常时,通过合理的日志记录,我们可以迅速定位问题,了解问题的来龙去脉。

30天拿下Python之logging模块_logging模块


logging的基本使用

在Python中,logging模块的使用比较简单。导入logging模块后,通过调用basicConfig方法可以进行基本的配置。比如:可以设置日志级别、日志输出位置、日志格式等。

import logging
logging.basicConfig(level = logging.INFO,
                    format = '%(asctime)s - %(levelname)s - %(message)s',
                    filename = 'app.log',
                    filemode = 'w')

进行上述的基本配置后,我们就可以创建logger对象,并调用其各种方法来记录日志信息了。

logger = logging.getLogger('my_logger')
logger.debug('Debug message')
logger.info('Info message')
logger.warning('Warning message')
logger.error('Error message')
logger.critical('Critical message')

执行上述的示例代码后,会在当前目录下生成app.log文件,其内容如下。

2023-09-24 19:44:43,086 - INFO - Info message
2023-09-24 19:44:43,086 - WARNING - Warning message
2023-09-24 19:44:43,086 - ERROR - Error message
2023-09-24 19:44:43,086 - CRITICAL - Critical message

可以看到,logger.debug函数写入的调试信息没有出现在文件中。这是因为,我们指定了日志级别为logging.INFO,比该日志级别低的信息会被过滤掉,不会写入日志文件中。


logging的选项设置

logging模块提供了很多选项来配置日志记录的行为,以下是一些常见的选项。

日志记录器名称:每个记录器都有一个名称,可以通过名称来获取和配置特定的记录器。

日志级别:一共有五个级别的日志记录,从低到高依次为:DEBUG、INFO、WARNING、ERROR、

CRITICAL。我们可以设置日志记录器的级别,这样低于该级别的所有消息都不会被记录。比如:如果级别设置为WARNING,那么DEBUG和INFO级别的消息将不会被记录。

日志格式:可以通过设置日志记录器的格式字符串来改变日志消息的显示方式。比如:可以包含时间戳、日志级别、消息、线程名等。

日志输出地:日志消息可以输出到多种地方,比如:控制台、文件等。可以使用多种Handler来实现,比如:输出到控制台使用StreamHandler、输出到文件使用FileHandler等。

日志旋转:如果日志文件可能会变得很大,我们需要在满足某个条件(比如:日志文件达到一定大小)时创建一个新的日志文件,这可以通过使用RotatingFileHandler或TimedRotatingFileHandler等处理程序来实现。

日志过滤:可以通过使用过滤器来进一步定制哪些消息应该被记录。比如:我们可以设置一个过滤器,只有包含特定关键字的消息才会被记录。

在下面的示例代码中,我们创建了一个名为'my_logger'的日志记录器,并设置了其级别为DEBUG。然后,我们创建了一个写入日志文件的处理器和一个输出到控制台的处理器,并设置了他们的级别。我们还定义了日志消息的格式,并将其应用到了两个处理器上。最后,我们用这个记录器记录了一条警告信息。

import logging

# 创建一个logger
logger = logging.getLogger('my_logger')
# 设置日志级别
logger.setLevel(logging.DEBUG)
  
# 创建一个Handler,用于写入日志文件
fileHandler = logging.FileHandler('app.log')
# 设置日志级别
fileHandler.setLevel(logging.DEBUG)

# 创建一个Handler,用于输出到控制台
consoleHandler = logging.StreamHandler()
# 设置日志级别
consoleHandler.setLevel(logging.INFO)

# 定义Handler的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fileHandler.setFormatter(formatter)
consoleHandler.setFormatter(formatter)

# 给logger添加Handler
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)

# 记录一条日志
# 输出:2023-09-24 20:06:26,828 - my_logger - WARNING - a warning info
logger.warn('a warning info')


日志旋转

在logging模块中,可以使用RotatingFileHandler和TimedRotatingFileHandler来实现日志旋转。

RotatingFileHandler根据日志文件的大小来旋转日志文件。可以通过设置maxBytes参数来指定每个日志文件的大小,同时通过backupCount参数来指定保留的备份文件数量。当日志文件达到设定的最大大小时,原日志文件将被重命名并备份,同时开始写入新的日志文件。

TimedRotatingFileHandler则根据时间间隔来旋转日志文件。可以通过设置interval参数来指定时间间隔,同时通过backupCount参数来指定保留的备份文件数量。当达到设定的时间间隔时,原日志文件将被重命名并备份,同时开始写入新的日志文件。

import logging
import logging.handlers
  
# 创建一个Logger对象
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

# 创建一个RotatingFileHandler对象
maxSize = 1 << 20
handler = logging.handlers.RotatingFileHandler('app.log', maxBytes = maxSize, backupCount = 5)
  
# 设置日志级别和格式
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

# 记录日志消息
logger.info('Info message')

在上面的示例代码中,我们创建了一个RotatingFileHandler对象,并指定了日志文件的最大大小为1MB字节,同时保留5个备份文件。当日志文件达到设定的最大大小时,原日志文件将被重命名并备份,同时开始写入新的日志文件。


logging.Filter类

logging.Filter类用于过滤日志消息。它有一个名为filter的函数,用于确定是否应该记录或传递日志消息。我们可以创建一个Filter类的派生类,并覆盖其filter函数。该函数接受一个日志记录对象作为参数,并返回一个布尔值,用于表示是否应该记录或传递该日志消息。如果该函数返回True,则日志消息将被记录或传递,否则将被忽略。

import logging  
  
LOG_FORMAT = '%(levelname)s %(asctime)s - %(message)s'
logging.basicConfig(filename = "app.log", level = logging.DEBUG, format = LOG_FORMAT)

my_logger = logging.getLogger('my_logger')
my_logger.setLevel(logging.DEBUG)

# 创建一个名为my_handler的处理器,并将其添加到my_logger中
my_handler = logging.StreamHandler()
my_handler.setLevel(logging.DEBUG)
my_handler.setFormatter(logging.Formatter(LOG_FORMAT))
my_logger.addHandler(my_handler)
  
# 创建一个名为filter的过滤器,并将其添加到my_handler中
class CustomFilter(logging.Filter):
    def filter(self, record):
        return 'Hope' in record.msg
filter = CustomFilter()
my_handler.addFilter(filter)
  
# 记录一些消息
my_logger.debug('Hello Hope')
my_logger.info('Hello World')
my_logger.warning('Hope web site')
my_logger.error('GitHub web site')

在上面的示例代码中,我们首先使用basicConfig方法定义了一个基本的日志配置。然后,创建了一个名为my_logger的记录器,并将其级别设置为DEBUG。接下来,我们创建了一个名为my_handler的处理器,并将其添加到my_logger中。我们还创建了一个名为filter的过滤器,并将其添加到my_handler中,以过滤掉日志信息中不包含"Hope"字符串的日志。最后,我们使用my_logger记录了几条不同级别的日志消息。执行上面的代码后,只有“Hello Hope”和“Hope web site”这两条日志信息会被保存和输出。


💡 如果想阅读最新的文章,或者有技术问题需要交流和沟通,可搜索并关注微信公众号“希望睿智”。