相关链接

第二篇:高级配置与日志处理器

在开发过程中,日志系统不仅仅是简单的消息输出工具,它可以通过不同的配置实现更为强大的功能,包括日志轮转、时间控制、格式化和过滤等。本文将深入探讨日志处理器、日志格式器和日志过滤器的高级配置,结合模拟实践进行演示。

日志处理器(Handlers)

日志处理器是 logging 模块的核心组件之一,它决定了日志消息的输出位置。常用的日志处理器包括:

  • StreamHandler: 将日志输出到控制台或其他流。
  • FileHandler: 将日志输出到文件。
  • RotatingFileHandler: 将日志输出到文件,并在文件达到指定大小时进行轮转。
  • TimedRotatingFileHandler: 将日志输出到文件,并在指定时间间隔后进行轮转。

StreamHandler

StreamHandler 将日志输出到控制台或其他流(如 sys.stdoutsys.stderr)。

StreamHandler.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import logging

# 创建日志记录器
logger = logging.getLogger('stream_logger')
logger.setLevel(logging.DEBUG)

# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# 创建并设置日志格式器
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')
logger.info('This is an INFO message')
logger.warning('This is a WARNING message')
logger.error('This is an ERROR message')
logger.critical('This is a CRITICAL message')

控制台输出:

1
2
3
4
5
2024-09-16 11:16:05,188 - stream_logger - DEBUG - This is a DEBUG message
2024-09-16 11:16:05,188 - stream_logger - INFO - This is an INFO message
2024-09-16 11:16:05,189 - stream_logger - WARNING - This is a WARNING message
2024-09-16 11:16:05,189 - stream_logger - ERROR - This is an ERROR message
2024-09-16 11:16:05,189 - stream_logger - CRITICAL - This is a CRITICAL message

FileHandler

FileHandler 将日志输出到指定文件。

FileHandler.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import logging

# 创建日志记录器
logger = logging.getLogger('file_logger')
logger.setLevel(logging.DEBUG)

# 创建文件处理器
file_handler = logging.FileHandler('log/file_log.log')
file_handler.setLevel(logging.DEBUG)

# 创建并设置日志格式器
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')
logger.info('This is an INFO message')
logger.warning('This is a WARNING message')
logger.error('This is an ERROR message')
logger.critical('This is a CRITICAL message')

log/file_log.log输出:

1
2
3
4
5
2024-09-16 11:20:29,829 - file_logger - DEBUG - This is a DEBUG message
2024-09-16 11:20:29,829 - file_logger - INFO - This is an INFO message
2024-09-16 11:20:29,829 - file_logger - WARNING - This is a WARNING message
2024-09-16 11:20:29,829 - file_logger - ERROR - This is an ERROR message
2024-09-16 11:20:29,829 - file_logger - CRITICAL - This is a CRITICAL message

RotatingFileHandler

RotatingFileHandler 将日志输出到文件,并在文件达到指定大小时进行轮转。它可以保留多个备份文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import logging
from logging.handlers import RotatingFileHandler
import os

# 获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))

# 定义日志文件的路径
log_file_path = os.path.join(script_dir, 'log/rotating_file.log')

# 创建日志记录器
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG) # 设置日志记录器的日志级别

# 创建控制台处理器并设置日志级别
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# 创建文件轮转处理器并设置日志级别
# rotating_file_handler = RotatingFileHandler(log_file_path, maxBytes=1*1024*1024, backupCount=5) # 1MB
rotating_file_handler = RotatingFileHandler(log_file_path, maxBytes=1*1024, backupCount=5) # 1KB
rotating_file_handler.setLevel(logging.INFO)

# 创建格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 将格式化器添加到处理器
console_handler.setFormatter(formatter)
rotating_file_handler.setFormatter(formatter)

# 将处理器添加到日志记录器
logger.addHandler(console_handler)
logger.addHandler(rotating_file_handler)

# 测试日志输出
for i in range(10000):
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

log目录:

TimedRotatingFileHandler

TimedRotatingFileHandler 将日志输出到文件,并在指定时间间隔后进行轮转。例如,每天创建一个新的日志文件。

TimedRotatingFileHandler.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import logging
from logging.handlers import TimedRotatingFileHandler
import os

# 获取脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))

# 定义日志文件的路径
log_file_path = os.path.join(script_dir, 'log/timed_rotating_file.log')

# 创建日志记录器
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

# 创建控制台处理器并设置日志级别
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# 创建时间轮转处理器,每分钟轮转一次日志文件
timed_rotating_handler = TimedRotatingFileHandler(log_file_path, when="M", interval=1, backupCount=5)
timed_rotating_handler.setLevel(logging.INFO)

# 创建格式化器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 将格式化器添加到处理器
console_handler.setFormatter(formatter)
timed_rotating_handler.setFormatter(formatter)

# 将处理器添加到日志记录器
logger.addHandler(console_handler)
logger.addHandler(timed_rotating_handler)

# 测试日志输出
for i in range(100):
logger.debug('This is a debug message')
logger.info('This is an info message')
logger.warning('This is a warning message')
logger.error('This is an error message')
logger.critical('This is a critical message')

第一次运行代码,注意log前10行的输出。

隔几分钟第二次运行代码,我们会发现文件重置了:

日志格式器(Formatters)

日志格式器用于定义日志消息的显示格式。格式器通过指定格式字符串来控制日志输出的外观。

常用格式字符串:

  • %(asctime)s: 日志记录时间
  • %(name)s: 日志记录器的名称
  • %(levelname)s: 日志级别
  • %(message)s: 日志消息内容

Formatters.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import logging

# 创建日志记录器
logger = logging.getLogger('formatted_logger')
logger.setLevel(logging.DEBUG)

# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# 创建并设置不同的日志格式器
formatter1 = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
formatter2 = logging.Formatter('%(levelname)s: %(message)s (%(asctime)s)')

console_handler.setFormatter(formatter1)

# 将处理器添加到日志记录器
logger.addHandler(console_handler)

# 记录日志
logger.debug('This is a DEBUG message')
logger.info('This is an INFO message')

# 切换日志格式器
console_handler.setFormatter(formatter2)

# 记录更多日志
logger.warning('This is a WARNING message')
logger.error('This is an ERROR message')
logger.critical('This is a CRITICAL message')

控制台输出:

1
2
3
4
5
2024-09-16 11:39:34,945 - formatted_logger - DEBUG - This is a DEBUG message
2024-09-16 11:39:34,946 - formatted_logger - INFO - This is an INFO message
WARNING: This is a WARNING message (2024-09-16 11:39:34,946)
ERROR: This is an ERROR message (2024-09-16 11:39:34,946)
CRITICAL: This is a CRITICAL message (2024-09-16 11:39:34,946)

日志过滤器(Filters)

日志过滤器用于过滤日志记录器生成的日志消息。过滤器可以基于自定义规则筛选日志消息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import logging

class CustomFilter(logging.Filter):
def filter(self, record):
# 仅允许记录包含 'special' 关键字的日志消息
return 'special' in record.msg

# 创建日志记录器
logger = logging.getLogger('filtered_logger')
logger.setLevel(logging.DEBUG)

# 创建控制台处理器
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.DEBUG)

# 创建并设置日志格式器
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
console_handler.setFormatter(formatter)

# 创建并添加日志过滤器
custom_filter = CustomFilter()
console_handler.addFilter(custom_filter)

# 将处理器添加到日志记录器
logger.addHandler(console_handler)

# 记录日志
logger.debug('This is a DEBUG message')
logger.info('This is an INFO message with special keyword')
logger.warning('This is a WARNING message')
logger.error('This is an ERROR message with special keyword')
logger.critical('This is a CRITICAL message')

控制台输出:

1
2
2024-09-16 11:45:00,784 - filtered_logger - INFO - This is an INFO message with special keyword
2024-09-16 11:45:00,785 - filtered_logger - ERROR - This is an ERROR message with special keyword

文章总结

在本篇文章中,我们深入探讨了Python logging 模块的高级配置,重点介绍了如何使用不同的日志处理器(如StreamHandlerFileHandlerRotatingFileHandlerTimedRotatingFileHandler)来灵活控制日志的输出位置和方式。我们还讨论了日志格式器的使用,使得日志信息更直观、易读。通过应用日志过滤器,我们可以根据自定义规则过滤日志消息,从而提高日志的可控性和效率。

在第三篇文章中,我们将重点探讨如何在多模块项目中进行日志记录的协作。日志系统不仅仅是单一模块的工具,多个模块之间的日志管理需要统一配置和协作。我们将介绍如何在不同模块中使用相同的日志配置,确保日志消息能有效地集中管理和记录。同时,我们会详细讲解如何在各个模块中使用 debuginfowarningerrorcritical 等日志级别方法,记录不同类型的事件。此外,还将展示如何通过 exception 方法记录异常信息,保证错误信息在多模块项目中也能清晰呈现。