【Python 日志封神方案】logging 无缝桥接 loguru,FastAPI/Uvicorn 日志统一管控
·
作者:WangQiaomei版本:1.0
发布时间:2026-03-27
适用场景:Python 后端、FastAPI/Uvicorn 服务、日志统一格式化、多文件分级存储
🍋 前言:你是否被 Python 日志割裂问题搞疯?
做 Python 后端开发(尤其是FastAPI/Uvicorn)的同学一定踩过坑:
- 项目里用loguru优雅打日志,格式好看、功能强
- 但 Uvicorn、FastAPI 底层偏偏用标准 logging,日志格式混乱、两套体系
- 日志分级、文件切割、过期清理还要分别配置,维护成本拉满
👉 本文带来终极解决方案:标准 logging 全局拦截 + 无缝转发 loguru,一套配置统一所有日志,分级文件存储 + 自动轮转,源码直接复制即用!
🚀 方案核心优势
- 全日志统一:拦截所有标准 logging 日志(uvicorn/fastapi/ 第三方库),全部归 loguru 管理
- 分级存储:INFO/ERROR 日志分离文件,按天轮转、自动过期清理
- 精准溯源:日志行号 / 文件名精准指向真实调用处,无偏差
- 开箱即用:单模块封装,一行初始化,全局复用

🧩 核心组件详解
表格
| 组件 | 核心作用 |
|---|---|
| InterceptHandler | logging→loguru 桥接器,全局拦截标准日志并转发 |
| setup_logging() | 日志初始化入口,配置输出、轮转、保留策略 |
| logger | 导出 loguru 实例,全项目统一调用 |
📂 日志文件落地策略
表格
| 日志文件 | 输出级别 | 轮转规则 | 保留周期 |
|---|---|---|---|
logs/app_*.log | INFO 及以上 | 按天切割 | 保留 30 天 |
logs/error_*.log | ERROR 及以上 | 按天切割 | 保留 90 天 |
❓ 为什么要做 logging 桥接?
Uvicorn/FastAPI 底层强制依赖标准 logging,直接使用会出现:
python
运行
# 原生logging输出(丑、格式乱)
logging.info("Request received")
# 桥接后统一loguru格式(整洁、可追踪)
# 2026-03-24 17:30:00 | INFO | uvicorn:serve:123 - Request received
桥接后:所有日志(自研 + 第三方库)格式、级别、输出完全统一,再也没有两套日志体系!
💻 核心代码(logging.py)
python
运行
# -*- coding: utf-8 -*-
"""
日志配置模块
核心功能:拦截所有标准logging日志,转发至loguru统一处理
作者:WangQiaomei
版本:1.0(2026/3/27)
"""
import sys
import logging
from loguru import logger
# ============================================================
# 日志桥接器:标准logging → loguru
# ============================================================
class InterceptHandler(logging.Handler):
"""
全局桥接器:拦截标准logging所有日志,转发给loguru处理
解决FastAPI/Uvicorn底层logging与loguru格式割裂问题
"""
def emit(self, record: logging.LogRecord) -> None:
# 日志级别映射
try:
level = logger.level(record.levelname).name
except ValueError:
level = record.levelno
# 追溯真实调用栈(跳过logging内部帧,保证行号精准)
frame, depth = sys._getframe(6), 6
while frame and frame.f_code.co_filename == logging.__file__:
frame = frame.f_back
depth += 1
# 转发至loguru记录
logger.opt(depth=depth, exception=record.exc_info).log(
level, record.getMessage()
)
# ============================================================
# 日志全局初始化配置
# ============================================================
def setup_logging() -> None:
# 禁用标准logging默认处理器,防止重复输出
logging.basicConfig(handlers=[InterceptHandler()], level=0, force=True)
# 屏蔽无关第三方库冗余日志
for logger_name in [
"uvicorn", "uvicorn.access", "uvicorn.error",
"fastapi", "urllib3", "requests"
]:
logging.getLogger(logger_name).handlers = [InterceptHandler()]
logging.getLogger(logger_name).propagate = False
# 清空loguru默认配置
logger.remove()
# 1. INFO级别日志:文件输出,按天轮转,保留30天
logger.add(
sink="logs/app_{time:YYYY-MM-DD}.log",
level="INFO",
rotation="00:00", # 每日零点切割
retention=30, # 保留30天
encoding="utf-8",
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {name}:{function}:{line} - {message}"
)
# 2. ERROR级别日志:单独文件,按天轮转,保留90天
logger.add(
sink="logs/error_{time:YYYY-MM-DD}.log",
level="ERROR",
rotation="00:00",
retention=90,
encoding="utf-8",
format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {name}:{function}:{line} - {message}"
)
# 3. 控制台输出(开发调试用)
logger.add(
sink=sys.stdout,
level="INFO",
colorize=True,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level}</level> | <cyan>{name}:{function}:{line}</cyan> - <message>{message}</message>"
)
# 导出loguru实例,全项目统一调用
__all__ = ["setup_logging", "logger"]
🔧 一行接入全项目
在项目入口文件(main.py)仅需一行初始化:
python
运行
from core.logging import setup_logging
# 初始化全局日志
setup_logging()
# 后续全项目使用
from core.logging import logger
logger.info("业务日志测试")
logger.error("异常日志测试")
🎯 最终效果展示
控制台输出(彩色、带行号)
plaintext
2026-03-24 17:30:00 | INFO | main:<module>:10 - 业务日志测试
2026-03-24 17:30:01 | ERROR | main:<module>:11 - 异常日志测试
文件输出(分级存储、自动切割)
plaintext
logs/
├─ app_2026-03-24.log # INFO+日志,保留30天
└─ error_2026-03-24.log # ERROR+日志,保留90天
Uvicorn 底层日志也被统一接管
plaintext
2026-03-24 17:35:22 | INFO | uvicorn.server:serve:77 - Uvicorn running on http://127.0.0.1:8000
📌 总结
这套logging→loguru 桥接方案,完美解决 Python 后端日志割裂问题,分级存储、自动轮转、全局统一,适配 FastAPI/Uvicorn 等主流框架,生产环境直接落地!
源码高度封装、无侵入性,复制即用,再也不用为两套日志体系头疼~
更多推荐


所有评论(0)