欢迎光临
我们一直在努力

Python 3.12 logging - 18 - handlers - RotatingFileHandler

Python 3.12 logging Handler – RotatingFileHandler 详解

RotatingFileHandler 是 Python logging 模块中用于实现日志文件大小轮转的处理器。当日志文件达到指定大小时,它会自动关闭当前文件,重命名并备份,然后创建新的日志文件继续写入。这种机制可以有效防止单个日志文件无限增长,同时保留历史日志记录。


一、RotatingFileHandler 核心概念

1.1 工作原理

  • 程序持续向当前日志文件(如 app.log)写入日志。
  • 当文件大小达到 maxBytes 阈值时,触发轮转操作。
  • 将当前文件重命名为 app.log.1,原有的 app.log.1 变为 app.log.2,以此类推。
  • 创建新的空文件 app.log 继续写入。
  • 最多保留 backupCount 个备份文件,超出数量的最旧文件被删除。

1.2 适用场景

  • 长时间运行的服务(Web 应用、后台任务)
  • 日志量较大的系统
  • 需要保留历史日志但磁盘空间有限的环境

二、RotatingFileHandler 完整配置项解析

参数类型默认值说明
filename str 必需 日志文件路径(可绝对或相对)
mode str 'a' 文件打开模式,必须使用 'a'(追加),不能使用 'w',否则轮转时会清空文件内容
maxBytes int 0 单个日志文件最大字节数。设为 0 表示不轮转
backupCount int 0 保留的备份文件数量。如果设为 5,则备份文件为 .1 .2 … .5
encoding str None 文件编码,如 'utf8'
delay bool False 是否延迟打开文件直到第一条日志写入
errors str None 编码错误处理方式,如 'ignore'、'replace'

2.1 特殊属性(高级定制)

  • namer:可调用的命名函数,用于自定义备份文件的名称。
  • rotator:可调用的轮转函数,用于自定义轮转行为(如压缩)。

三、Demo 1:基础配置(按大小轮转)

本示例演示最基本的 RotatingFileHandler 配置,当日志文件达到 1KB 时自动轮转,保留 3 个备份。

3.1 Python 代码

import logging
from logging.handlers import RotatingFileHandler
import time

def demo1_basic_rotation():
# 1. 创建 logger
logger = logging.getLogger('demo1')
logger.setLevel(logging.DEBUG)

# 2. 创建 RotatingFileHandler
# 文件大小设为 1KB,保留 3 个备份
handler = RotatingFileHandler(
filename='demo1.log',
mode='a', # 必须使用追加模式
maxBytes=10240, # 10KB
backupCount=3,
encoding='utf-8'
)

# 3. 设置日志格式
formatter = logging.Formatter(
'%(asctime)s – %(name)s – %(levelname)s – %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)

# 4. 将处理器添加到 logger
logger.addHandler(handler)

# 5. 写入大量日志,触发轮转
for i in range(1, 501):
time.sleep(0.01)
logger.info(f"这是第 {i} 条日志消息,用于测试轮转功能。")
# 每 10 条暂停一点,让输出可读
if i % 100 == 0:
print(f"已写入 {i} 条日志,请查看 demo1.log 及其备份文件")
time.sleep(0.5)

print("Demo1 完成,查看当前目录下的 demo1.log* 文件")

if __name__ == '__main__':
demo1_basic_rotation()

3.2 逐行代码解析

行号/段落代码说明
import logging 导入核心日志模块
from logging.handlers import RotatingFileHandler 导入轮转文件处理器
logger = logging.getLogger('demo1') 创建名为 ‘demo1’ 的日志器
logger.setLevel(logging.DEBUG) 设置日志器级别为 DEBUG,接受所有级别日志
handler = RotatingFileHandler(…) 实例化轮转处理器
filename='demo1.log' 指定日志文件名为 demo1.log
mode='a' 关键:必须使用追加模式,否则轮转时会丢失日志
maxBytes=10240 设置单个文件最大为 10KB,用于快速演示轮转
backupCount=3 保留 3 个备份文件:.1、.2、.3
encoding='utf-8' 指定 UTF-8 编码,避免中文乱码
formatter = logging.Formatter(…) 创建格式化器,定义日志输出格式
handler.setFormatter(formatter) 将格式化器应用到处理器
logger.addHandler(handler) 将处理器添加到日志器
for i in range(1, 501): 循环写入 500 条日志,确保触发多次轮转
logger.info(…) 记录 INFO 级别日志
time.sleep(0.5) 短暂暂停,让输出更易观察

3.3 运行结果分析

运行后,当前目录会生成如下文件:

demo1.log # 当前正在写入的日志文件
demo1.log.1 # (时间最近的日志)
demo1.log.2
demo1.log.3 # (在轮转顺序中编号最大)(时间最早的日志)

轮转过程:

  • 当 demo1.log 达到 1KB 时,它被重命名为 demo1.log.1。
  • 原有的 demo1.log.1 变为 demo1.log.2,demo1.log.2 变为 demo1.log.3。
  • 如果已有 demo1.log.3,它会被删除。
  • 创建新的空文件 demo1.log 继续写入。

  • 四、Demo 2:高级定制(自定义命名与压缩)

    本示例展示如何使用 namer 和 rotator 实现备份文件的自动压缩(gzip),这是生产环境中节省磁盘空间的常用技巧 。

    4.1 Python 代码

    import logging
    from logging.handlers import RotatingFileHandler
    import gzip
    import os
    import shutil

    def demo2_custom_rotation():
    """
    演示自定义 namer 和 rotator,实现备份文件自动 gzip 压缩
    """

    # 1. 定义命名函数:为备份文件添加 .gz 后缀
    def namer(name):
    """
    参数 name: 原始备份文件名(如 demo2.log.1)
    返回: 压缩后的文件名(如 demo2.log.1.gz)
    """

    return name + ".gz"

    # 2. 定义轮转函数:对备份文件进行压缩
    def rotator(source, dest):
    """
    参数 source: 轮转前的原文件路径(如 demo2.log)
    参数 dest: 轮转后的目标文件路径(如 demo2.log.1)
    此函数会在文件重命名后调用,对 dest 进行压缩
    """

    with open(source, 'rb') as f_in:
    with gzip.open(dest, 'wb') as f_out:
    shutil.copyfileobj(f_in, f_out)
    # 压缩完成后删除原文件
    os.remove(source)

    # 3. 创建 logger
    logger = logging.getLogger('demo2')
    logger.setLevel(logging.INFO)

    # 4. 创建 RotatingFileHandler
    handler = RotatingFileHandler(
    filename='demo2.log',
    maxBytes=1024, # 1KB,快速演示
    backupCount=5,
    encoding='utf-8'
    )

    # 5. 挂载自定义 namer 和 rotator
    handler.namer = namer
    handler.rotator = rotator

    # 6. 设置格式
    formatter = logging.Formatter(
    '%(asctime)s – %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
    )
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    # 7. 写入日志,触发轮转
    for i in range(1, 301):
    logger.info(f"Message no. {i} – 这条日志用于测试压缩轮转。")
    if i % 50 == 0:
    print(f"已写入 {i} 条日志,查看 demo2.log* 文件")

    print("\\nDemo2 完成,生成的文件如下(压缩文件为 .gz):")
    for f in os.listdir('.'):
    if f.startswith('demo2.log'):
    size = os.path.getsize(f)
    print(f" {f}{size} bytes")

    if __name__ == '__main__':
    demo2_custom_rotation()

    4.2 逐行代码解析

    代码片段说明
    def namer(name): return name + ".gz" 命名函数:接收原始备份文件名(如 demo2.log.1),返回实际应使用的文件名。此处加上 .gz 后缀。
    def rotator(source, dest): 轮转函数:参数 source 是轮转前的原文件,dest 是目标备份文件名。函数内部使用 gzip.open 压缩 source 的内容写入 dest,然后删除原文件。
    handler.namer = namer 将自定义命名函数赋值给 handler,影响备份文件的命名。
    handler.rotator = rotator 将自定义轮转函数赋值给 handler,替代默认的重命名行为。
    with gzip.open(dest, 'wb') as f_out 以二进制写入模式打开 gzip 文件,shutil.copyfileobj 将原文件内容复制到压缩文件中。
    os.remove(source) 压缩完成后删除未压缩的原文件,节省空间。

    4.3 运行结果分析

    运行后,当前目录会生成如下文件:

    demo2.log # 当前正在写入的日志文件
    demo2.log.1.gz # 被压缩的备份文件
    demo2.log.2.gz
    demo2.log.3.gz
    demo2.log.4.gz
    demo2.log.5.gz

    特点:

    • 备份文件自动以 .gz 结尾,可以使用 zcat 或 gunzip 查看内容。
    • 文件大小显著减小(尤其对于文本日志)。
    • 该技术广泛用于生产环境日志管理 。

    五、配置注意事项

    5.1 mode 参数必须为 'a'

    RotatingFileHandler 内部依赖追加模式进行轮转。如果错误地设置为 'w',每次轮转时会清空当前文件内容,导致日志丢失。永远不要使用 'w' 。

    5.2 maxBytes 与 backupCount 的关系

    • 如果 maxBytes 为 0,轮转永远不会发生(文件无限增长)。
    • 如果 backupCount 为 0,轮转发生时只重命名当前文件,不保留任何备份(即旧文件被直接覆盖)。
    • 合理设置这两个值可以平衡磁盘占用与历史日志保留需求 。

    5.3 文件命名规则

    默认情况下,备份文件命名为 原文件名.1、原文件名.2 等,数字越大表示越旧的日志。通过 namer 可以自定义这一规则 。

    5.4 多进程安全

    RotatingFileHandler 不是多进程安全的。如果在多进程环境中同时写入同一文件,可能会导致日志错乱或轮转失败。解决方案:

    • 使用 QueueHandler + QueueListener 将日志集中到单进程处理。
    • 使用 concurrent_log_handler 第三方库。

    5.5 性能影响

    每次写入日志时,RotatingFileHandler 会检查当前文件大小,频繁的 stat 调用可能对极高吞吐量的系统有轻微影响。对于绝大多数应用,这种开销可忽略不计。


    六、总结

    RotatingFileHandler 是 Python logging 模块中最实用的处理器之一,通过合理的参数配置,可以轻松实现:

    功能实现方式
    按大小轮转 maxBytes + backupCount
    保留历史备份 backupCount 控制数量
    自定义备份名 namer 函数
    备份压缩 rotator 函数实现 gzip

    掌握这些配置,你就能构建一个健壮、高效的日志管理系统,既避免磁盘爆满,又保留必要的追溯信息。

    如果在学习过程中遇到问题,欢迎在评论区留言讨论!

    赞(0)
    未经允许不得转载:171主机测评 » Python 3.12 logging - 18 - handlers - RotatingFileHandler
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址