FastAPI集成Loguru日志轮转遇Windows权限错误求助
问题原因分析
- 文件权限错误:你启用了uvicorn的
reload=True热重载模式,该模式会启动两个进程——主进程负责监控文件变化并重启应用,子进程才是实际运行FastAPI的进程。两个进程都会执行logger.add("out-1.log"),导致同一个日志文件被两个进程同时占用。Windows系统不允许重命名被进程锁定的文件,因此日志轮转时触发PermissionError。 - 随机文件名生成2个文件:同样是因为热重载模式下的两个进程各自执行日志初始化代码,每个进程生成不同的随机文件名,所以启动后会出现两个独立的日志文件。
解决方法
方法1:仅让子进程添加文件日志处理器
修改日志配置代码,判断当前进程是否为uvicorn重载主进程,仅子进程添加文件日志处理器:
import os from loguru import logger import sys import random import global_vars def formatter(record): record["message"] = f"{random.randrange(0, 100)}\n" return "{time} | <red>{level}</red> | {extra[trace_id]} | {extra[microservice_name]} | {message}" logger.remove(0) logger = logger.bind(trace_id=global_vars.trace_id.get(), microservice_name=global_vars.microservice_name.get()) # uvicorn重载主进程会自动设置UVICORN_RELOADER环境变量,仅子进程添加文件日志 if not os.environ.get("UVICORN_RELOADER"): logger.add( "out-1.log", level="DEBUG", format=formatter, rotation="30 seconds", retention="1 week", colorize=True ) # 标准输出不受进程影响,正常添加 logger.add(sys.stdout, level="DEBUG", format=formatter, colorize=True, diagnose=False)
方法2:关闭uvicorn热重载(生产环境推荐)
如果不需要开发时的热重载功能,直接将uvicorn.run的reload=True改为reload=False,这样只会启动一个进程,不会出现文件占用问题:
if __name__ == "__main__": uvicorn.run("main:app", reload=False)
额外优化
- 移除formatter函数里的
print(record)语句,避免不必要的控制台冗余输出。 - 确保
global_vars.trace_id和microservice_name在子进程中能正确获取值,避免日志字段缺失。
内容的提问来源于stack exchange,提问作者user13084415
相关产品推荐
相关产品推荐

