RotatingFileHandler按大小轮转,TimedRotatingFileHandler按时间轮转;前者依赖maxBytes和backupCount控制单文件大小与保留数量,后者通过when、interval和atTime精确调度滚动时机,但均不支持多进程安全写入。
用 RotatingFileHandler 实现按大小滚动日志
当单个日志文件容易膨胀到几百MB甚至GB时,RotatingFileHandler 是最直接的解法。它不依赖外部工具,纯Python内置,适合大多数后台服务。
关键点在于控制单个文件上限和保留备份数量,否则磁盘可能被旧日志占满:
-
maxBytes设太小(比如 1KB)会导致频繁切文件,影响 I/O 性能;建议设为10*1024*1024(10MB)起 -
backupCount决定最多保留几个历史文件,设为5表示只留当前 + 最近 5 个,超出的自动删除 - 注意:它不会主动压缩旧文件,若需压缩,得自己在
doRollover()中重写逻辑或用TimedRotatingFileHandler配合backupCount
import logging
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
filename="app.log",
maxBytes=10*1024*1024,
backupCount=5,
encoding="utf-8"
)
logger = logging.getLogger("myapp")
logger.addHandler(handler)
logger.setLevel(logging.INFO)
用 TimedRotatingFileHandler 按时间滚动(如每天/每小时)
需要按自然周期归档(比如每天一个日志文件、每小时切一次),就选 TimedRotatingFileHandler。它支持 when 参数指定滚动单位,但行为容易被误解:
-
when="D"表示“每天午夜”,不是“运行后 24 小时”。如果程序凌晨 3 点启动,第一次滚动仍发生在次日 0 点 -
when="H"是整点滚动,不是“每 60 分钟”,即 14:00 启动,下次滚动是 15:00,不是 14:60(不存在) -
interval和when要匹配:设when="S"(秒)再配interval=30才是每 30 秒切一次;但高频滚动会生成大量小文件,慎用 - 默认文件名后缀是
.2024-05-20这类,若想带时分秒(如.2024-05-20_14),需设置utc=True或自定义suffix
为什么 TimedRotatingFileHandler 容易漏滚或重复滚?
根本原因是它靠首次写入时间推算下次滚动时刻,且不持久化记录。常见问题包括:
立即学习“Python免费学习笔记(深入)”;
Python 3.14.3
微软官方的 Python 扩展,是 VS Code 安装量最高的扩展(209M+)。集成 IntelliSense(通过 Pylance)、调试(通过 Python Debugger)、代码检查、格式化、重构和单元测试等功能。支持 Jupyter Notebook、虚拟环境管理和多 Python 版本切换。
- 程序中途重启:如果上次滚动是 02:00,重启在 02:30,它会把“下一次该滚的时间”重算为 03:00,跳过 02:00–02:30 的间隔 —— 这段日志就全挤进 02:00 文件里
- 多进程写同一日志路径:各进程独立判断滚动时机,可能同时触发 rename,导致部分日志丢失或文件损坏(Python 官方明确不保证多进程安全)
- 系统时间回拨(如 NTP 校准):handler 可能误判“已到滚动点”,反复 rename 同一文件,产生
.2024-05-20.1、.2024-05-20.2等冗余后缀
解决办法只有两个:要么用外部日志轮转工具(如 logrotate),要么改用单进程 + 看门狗管理日志目录。
生产环境更推荐组合方案:Rotating + 外部 logrotate
Python 自带 handler 在简单场景够用,但一旦涉及高可用、多实例、精确归档策略(比如“保留 30 天且自动 gzip”),硬靠 Python 处理反而增加不确定性。
典型做法是让 Python 只写一个固定名日志(如 app.log),然后用系统级 logrotate 管理滚动:
- logrotate 支持
dateext、compress、maxage、copytruncate(避免应用重启)等精细控制 - Python 不用关心滚动逻辑,
FileHandler即可,减少代码复杂度和潜在 bug - 唯一要注意的是:logrotate 的
create指令权限要和 Python 进程一致,否则新文件可能因权限不足写不进去
滚动机制本身不难,难的是滚动时机是否可靠、历史文件是否可控、出错时能否快速定位 —— 这些恰恰是纯 Python 方案最容易模糊处理的地方。