rotatingfilehandler 日志不滚动的主因是 maxbytes 或 backupcount 配置错误、多进程共用实例、或日志含超长无换行字符串;需设 maxbytes>0(如5mb)、backupcount≥1、避免共享实例,并用 ls -l 查实际字节数验证。

为什么直接用 RotatingFileHandler 有时不生效?
常见现象是日志文件没按预设大小切分,反而越写越大。根本原因通常是:没正确设置 maxBytes 和 backupCount,或在多进程/多线程环境下共享了同一个 RotatingFileHandler 实例(它本身不是进程安全的)。另外,如果日志内容含大量未换行的长字符串(比如一整段 JSON),RotatingFileHandler 仍会等写满 maxBytes 才滚动——它按字节计,不是按行。
-
maxBytes必须大于 0,且建议设为合理值(如10 * 1024 * 1024表示 10MB);设为 0 或负数会导致禁用滚动 -
backupCount控制保留几个历史文件,设为 0 表示不删除旧文件,磁盘可能被撑爆 - 避免在多个进程里共用同一 handler 实例;若需多进程写日志,考虑用
concurrent-log-handler替代,或改用日志服务器
如何配置一个最小可用的滚动日志处理器?
下面这段代码能立刻跑起来,生成 app.log,超过 5MB 就重命名为 app.log.1,最多保留 3 个旧文件:
import logging
from logging.handlers import RotatingFileHandler
<p>handler = RotatingFileHandler(
filename='app.log',
maxBytes=5 <em> 1024 </em> 1024, # 5MB
backupCount=3,
encoding='utf-8'
)
handler.setFormatter(logging.Formatter('%(asctime)s - %(levelname)s - %(message)s'))
logger = logging.getLogger('myapp')
logger.setLevel(logging.INFO)
logger.addHandler(handler)</p><p>logger.info('Hello world') # 这行会写入 app.log
</p>
注意:encoding='utf-8' 建议显式指定,尤其在 Windows 上避免中文乱码;filename 路径支持相对路径,但生产环境建议用绝对路径(如 /var/log/myapp/app.log)。
让 macOS 自动化像说话一样简单 —— 用代码控制你的 Mac,无需学习 AppleScript 系统要求 macOS 14+ (Sonoma) Python 3.9+ 需要开启:辅助功能 + 屏幕录制权限
为什么日志滚动后旧文件名带数字却不按时间排序?
RotatingFileHandler 默认按数字后缀命名(.1、.2…),且数字越大表示越旧——这是设计行为,不是 bug。比如当前是 app.log,滚动一次变成 app.log.1,再滚动变成 app.log.1 → app.log.2,app.log → app.log.1。所以 ls -t 看不到时间顺序,得用 ls -v(版本序)或靠数字后缀判断新旧。
- 如果必须按日期命名(如
app-2024-06-01.log),不能用RotatingFileHandler,得换TimedRotatingFileHandler,但它按时间滚动,不按大小 - 想兼顾大小 + 日期命名?得自己继承
RotatingFileHandler重写doRollover(),成本高,一般没必要 - 线上排查时,别依赖文件修改时间判断日志新旧,优先看文件名后缀数字
调试滚动失败时该查哪几个关键点?
当发现日志没滚动,先快速验证这三处:
- 检查实际写入的字节数是否真超了
maxBytes:用ls -l app.log看大小,注意单位是字节,不是 KB/MB 显示值 - 确认没其他代码重复调用
addHandler():多次添加同一 handler 会导致内部计数错乱,滚动失效 - 验证
backupCount是否被设为 0 或负数:此时旧文件不会被删除,但新日志仍会追加到当前文件,看起来像“没滚动”
滚动逻辑只在每次写入前检查文件大小,所以小日志量下可能几天都不触发;别等几秒就怀疑配置错了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










