在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的核心价值在于:按时间自动切分日志 + 控制历史数量,用最少的代码实现日志文件的自管理。 |