Flask默认日志不支持按日期切割,需用TimedRotatingFileHandler并清空默认handler;正确配置包括clear handlers、设置utc=True、预建logs目录、避免重复输出。

Flask 默认日志不支持按日期切割,得换 RotatingFileHandler 或 TimedRotatingFileHandler
Flask 自身只提供 logger 接口,底层用的是 Python 标准库 logging,它默认的 FileHandler 不会切文件。真要按天生成日志(比如 app-2024-06-15.log),必须显式替换 handler。推荐用 TimedRotatingFileHandler,它原生支持 when='midnight' 和 backupCount 控制保留天数。
常见错误是直接对 app.logger 调用 addHandler 却没先清空默认 handler,结果日志重复输出两遍。正确做法是先调用 app.logger.handlers.clear()。
-
when='midnight'表示每天 0 点触发切割,配合interval=1(默认)和backupCount=7可保留最近 7 天日志 -
utc=True可避免时区切换导致切割错乱(尤其部署在 Docker 或 UTC 服务器时) - 文件名里别硬编码日期——
TimedRotatingFileHandler会自动在文件名后追加时间戳,如app.log.2024-06-15;若想要app-2024-06-15.log这种格式,得重写doRollover或改用第三方库(如watchtower不适用此场景)
手动配置 TimedRotatingFileHandler 的最小可行代码
不要依赖 Flask 的 app.logger.addHandler 自动继承,从头配更可控。关键是把 formatter、level、rotation 参数一次性设全,否则可能漏字段或权限报错。
import logging
from logging.handlers import TimedRotatingFileHandler
from flask import Flask
<p>app = Flask(<strong>name</strong>)</p><h1>清掉 Flask 默认的 StreamHandler</h1><p>app.logger.handlers.clear()
app.logger.setLevel(logging.INFO)</p><h1>创建带时间切割的 handler</h1><p>handler = TimedRotatingFileHandler(
filename='logs/app.log',
when='midnight',
interval=1,
backupCount=7,
encoding='utf-8',
utc=True
)
handler.setLevel(logging.INFO)</p><h1>设置日志格式(含时间、级别、模块名、消息)</h1><p>formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
handler.setFormatter(formatter)</p><h1>挂载到 app.logger</h1><p>app.logger.addHandler(handler)</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill9386" title="python学习"><img
src="https://img.php.cn/upload/skill/000/000/081/179257684888086.jpg" alt="python学习" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill9386" title="python学习" class="overflowclass">python学习</a>
<p class="overflowclass">Python 编程学习助手 skill,面向零基础用户。 当用户表达以下意图时触发: - 学习 Python 基础概念(变量、数据类型、循环、函数、类等) - 请求 Python 练习题或测验 - 请求审查或调试 Python 代码 - 请求 Python 项目实战指导(爬虫、数据分析、Web 开发等入门项目) - 泛化表述如"教我 Python""我想学编程""Python 怎么写""帮我学 Python" 此 skill </p>
</div>
<a rel="nofollow" href="/xiazai/skill9386" title="python学习" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><p>@app.route('/')
def home():
app.logger.info('Request received')
return 'OK'</p>
注意 logs/ 目录权限和首次运行问题
如果 logs/ 目录不存在,TimedRotatingFileHandler 不会自动创建,启动时直接抛 FileNotFoundError。也不能指望 Flask 启动前就存在该目录——得在 handler 初始化前主动检查并创建。
- 用
os.makedirs('logs', exist_ok=True)确保目录存在,放在TimedRotatingFileHandler实例化之前 - Linux 部署时注意运行用户(如
www-data)是否有logs/写权限,否则日志静默失败,连错误都记不了 - Windows 下路径分隔符用
/或os.path.join更稳妥,避免反斜杠转义问题
调试时发现日志没按天切?先查这三处
最常卡在配置生效环节,不是代码逻辑问题,而是环境或加载时机不对。
- 确认
app.logger.handlers列表里只有你的TimedRotatingFileHandler,没有残留的StreamHandler(开发时容易忘记关 debug 模式) - 检查系统时间是否准确,尤其是容器内时间跟宿主机不同步会导致
midnight切割点漂移甚至失效 - 留意
TimedRotatingFileHandler的delay=True默认值:它延迟打开文件,首次 log 才真正初始化。如果应用启动后一直没打日志,文件不会被创建,看起来像“没生效”
日志切割本身不难,难的是让 handler 在所有部署环境里稳定触发——目录、权限、时区、加载顺序,任何一个没对齐,都会让你在凌晨三点翻日志时发现昨天的记录还挤在今天的文件里。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










