Python TimedRotatingFileHandler日志切割详
在Python的logging模块中,TimedRotatingFileHandler是一个按时间自动切割日志文件的处理器,适合长期运行的生产环境服务。它能每天、每小时甚至每分钟生成新日志文件,并通过backupCount控制历史数量,避免磁盘被日志占满。本文将详细讲解其参数含义、使用方式以及实际开发中常遇到的坑。import logging
from logging.handlers import TimedRotatingFileHandler
logger = logging.getLogger("my_logger")
logger.setLevel(logging.INFO)
handler = TimedRotatingFileHandler(
filename="app.log",
when="midnight",
interval=1,
backupCount=7,
encoding="utf-8"
)
handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s"))
logger.addHandler(handler)
logger.info("这是第一条日志")
上述代码实现了每天凌晨切割日志,并保留最近7天的历史文件。
参数详解
构造方法签名为:
TimedRotatingFileHandler(filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False)
[*]filename:当前写入的日志文件名,切割后该文件会被重命名(加上日期后缀),然后创建新的同名文件继续写入。
[*]when:最重要的参数,决定切割的时间单位。支持的值:
- 'S':每秒
- 'M':每分钟
- 'H':每小时
- 'D':每天
- 'W0'~'W6':周一至周日(注意:按周切割时底层会转为midnight,当周为interval的倍数时触发)
- 'midnight':每天午夜(00:00)切割,与'D'效果类似但更精确
[*]interval:与when配合,例如when='H', interval=6表示每6小时切割一次。
[*]backupCount:保留的历史日志文件数量,超过旧文件会被自动删除。例如backupCount=7,目录中最多有7个历史文件加上当前文件。
[*]encoding:强烈建议设置为'utf-8',避免中文乱码。
[*]utc:默认False,使用本地时间;设为True则使用UTC时间决定切割时机。
日志文件命名规则
当filename="app.log"时,切割后昨天生成的文件会被重命名为app.log.2026-04-26(根据日期),当前文件始终保持为app.log。不会自动给当前文件加日期后缀。
结合logging.basicConfig使用
如果想简化配置,可以直接在basicConfig中传入handlers列表:
import logging
from logging.handlers import TimedRotatingFileHandler
logging.basicConfig(
level=logging.INFO,
handlers=[
TimedRotatingFileHandler("app.log", when="D", interval=1, backupCount=15, encoding="utf-8")
],
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.info("服务启动")
同时输出到控制台和文件(推荐)
生产环境通常需要既看终端又存文件:
logger = logging.getLogger()
logger.setLevel(logging.INFO)
file_handler = TimedRotatingFileHandler("app.log", when="midnight", backupCount=7, encoding="utf-8")
console_handler = logging.StreamHandler()
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.addHandler(console_handler)
常见坑与注意事项
1. 多进程写同一个日志文件
TimedRotatingFileHandler不保证多进程安全,多个进程同时写入会导致日志混乱或文件损坏。
解决方案:每个进程使用独立日志文件,或使用ConcurrentLogHandler(第三方库),或在Linux下借助logrotate系统工具切割。
2. 修改系统时间导致切分异常
如果在运行中修改系统时间(比如回拨),可能导致切割逻辑出错,出现重复或丢失日志文件。Docker/K8s环境应确保容器时间同步。
3. 日志不立即写入
默认有缓冲(buffer),调试时可以手动调用handler.flush()强制写入。
适用场景
适合:Web服务、后台任务、定时任务等长期运行的程序。
不适合:超大日志量(建议按大小切割的RotatingFileHandler),以及多进程并发写同一文件(需要外部工具辅助)。
TimedRotatingFileHandler的核心价值在于:按时间自动切分日志 + 控制历史数量,用最少的代码实现日志文件的自管理。
Re: Python TimedRotatingFileHandler日志切割详
感谢分享,非常详细的讲解!你提到的“多进程写同一文件”这个坑我之前踩过,后来用了ConcurrentLogHandler才解决。另外关于`when="midnight"`和`when="D"`的区别,以前一直以为一样,原来`midnight`更精确,学到了。想请教一下:如果日志量特别大,每天切割会产生大量小文件,有没有比较推荐的策略?比如按小时切割并配合`backupCount`控制总量,会不会更合适?Re: Python TimedRotatingFileHandler日志切割详
感谢楼主这么详尽的分享!正好最近在优化一个长期运行的定时任务日志,准备从普通FileHandler换成TimedRotatingFileHandler,这篇帖子太及时了。 关于“修改系统时间导致切分异常”这个坑之前没太注意,您提醒后确实该在容器部署时确保NTP同步。另外我有个小疑问:如果when设为'W0'(周一),backupCount设成4,按周切割的话,是保留最近4周的周一文件还是按自然周数量保留?希望楼主或其他朋友指点一下。再次感谢!Re: Python TimedRotatingFileHandler日志切割详
感谢楼主详细的讲解,特别是参数定义和常见坑的部分非常实用。我之前也遇到过修改系统时间导致日志切割错乱的情况,确实需要小心。另外想请教一下,在多进程写同一日志文件时,除了改用第三方库或系统 logrotate,有没有什么轻量级的做法,比如用 SocketHandler 把日志统一发到单进程处理?期待更多经验分享。
页:
[1]