必须用timedrotatingfilehandler实现按天滚动,因其支持when='midnight'、utc=false等参数对齐本地零点;rotatingfilehandler仅按大小触发,不识别时间。

直接用 RotatingFileHandler 不行,它按文件大小切;要按天滚动,必须上 TimedRotatingFileHandler,且得避开 Django 默认配置的坑。
为什么 TimedRotatingFileHandler 在 Django 里常不生效?
Django 的日志配置如果写在 LOGGING 字典里但没显式指定 class,Django 会 fallback 到内置的 NullHandler 或忽略 handler 参数;更常见的是时区没对齐——TimedRotatingFileHandler 默认用系统本地时区判断“一天”,而 Django 的 TIME_ZONE 可能设为 'UTC',导致每天切割时间漂移(比如你期望凌晨 0 点切,实际变成 UTC 凌晨 0 点即北京时间上午 8 点)。
实操建议:
- 必须在
LOGGING['handlers']中显式写'class': 'logging.handlers.TimedRotatingFileHandler' - 加
'when': 'midnight'和'interval': 1(缺一不可,只写when不够) - 强制指定
'utc': False,让 handler 尊重系统本地时区(或统一设为TIME_ZONE对应的时区) - 确保日志目录存在且 Python 进程有写权限,否则静默失败
LOGGING 配置中关键字段怎么填?
下面这段可直接贴进 settings.py(路径和级别按需改):
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'rotating_file': {
'level': 'INFO',
'class': 'logging.handlers.TimedRotatingFileHandler',
'filename': '/var/log/myapp/django.log',
'when': 'midnight',
'interval': 1,
'backupCount': 30,
'encoding': 'utf-8',
'utc': False,
'formatter': 'verbose',
},
},
'formatters': {
'verbose': {
'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
'style': '{',
},
},
'loggers': {
'django': {
'handlers': ['rotating_file'],
'level': 'INFO',
'propagate': False,
},
},
}
注意点:
-
'backupCount': 30表示最多保留 30 个历史文件,超了自动删最老的 -
'filename'路径必须是绝对路径,相对路径容易因启动位置不同出错 -
'formatter'必须提前定义,否则 handler 初始化失败,日志全丢 - 别漏掉
'encoding': 'utf-8',否则中文日志可能乱码或报错
如何验证切割是否真在“每天零点”触发?
不能只看文件名后缀(如 django.log.2024-05-20),因为 TimedRotatingFileHandler 是在首次写日志时检查是否该切,不是后台定时轮询。真实行为是:服务启动后第一次写日志时,它比对当前时间和上次切割时间,差 1 天就切;之后每次写都检查一次。
快速验证方法:
- 手动改系统时间到临近 0 点(如 23:59:58),然后触发一个
logger.info("test") - 等两秒再写一条,观察是否生成新文件(如
django.log.2024-05-20和django.log同时存在) - 查
ls -lt /var/log/myapp/看文件修改时间是否卡在 00:00:00 附近 - 如果没切,立刻查 Django 启动日志里有没有
ValueError: Unknown level或Permission denied类错误
真正麻烦的是多进程部署场景(比如 gunicorn 多 worker)——TimedRotatingFileHandler 不支持进程间协调,可能多个进程同时尝试 rename 同一个文件,导致切割错乱或丢失日志。这种情况下,要么上 ConcurrentLogHandler(需 pip install),要么把日志转给 syslog 或 ELK 统一处理。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











