FastApi结合loguru日志使用

本文介绍了如何在FastAPI中使用loguru库替代Python内置日志模块,提供更灵活的配置和颜色输出。作者展示了如何配置loguru以管理FastAPI的所有日志,并优化了uvicorn的日志输出,实现日志的统一管理。
摘要由CSDN通过智能技术生成

 

        Python自带的日志logging模块使用起来比较麻烦,配置繁琐,所有打算使用一个配置简单,可自定义输出日志颜色的日志库loguru,相比于python自带的日志框架方便多了,这里我将介绍FastApi中使用loguru,我们先看看loguru输出日志的样式:

安装:

pip install loguru

72a6831be7184c079085119e882a989b.png

        使用loguru输出的日志看上去是不是很不错,可以设置输出的时间格式,日志输出的颜色,还有当前进程信息,输生日志打印的行数等都可以设置,为不同日志级别设置不同的输出日志的颜色便于查找日志信息。

        在FastApi刚加入loguru日志时,就是很简单的使用,在可能出现异常的地方加一句日志,这个我个人感觉就没很好的将loguru集成到FastAPI中,让loguru完全管理FastAPI的所有日志输出。

刚开始使用在FastApi中使用loguru时是这样做的,先配置一下loguru日志,创建一个log.py文件

log.py文件中的代码如下:

class Logger:
    """输出日志到文件和控制台"""

    def __init__(self):
        # 文件的命名
        log_name = f"Fast_{time.strftime('%Y-%m-%d', time.localtime()).replace('-', '_')}.log"
        log_path = os.path.join(LogPath, "Fast_{time:YYYY-MM-DD}.log")
        self.logger = logger
        # 清空所有设置
        self.logger.remove()
        # 判断日志文件夹是否存在,不存则创建
        if not os.path.exists(LogPath):
            os.makedirs(LogPath)
        # 日志输出格式
        formatter = "{time:YYYY-MM-DD HH:mm:ss} | {level}: {message}"
        # 添加控制台输出的格式,sys.stdout为输出到屏幕;关于这些配置还需要自定义请移步官网查看相关参数说明
        self.logger.add(sys.stdout,
                        format="<green>{time:YYYYMMDD HH:mm:ss}</green> | "  # 颜色>时间
                               "{process.name} | "  # 进程名
                               "{thread.name} | "  # 进程名
                               "<cyan>{module}</cyan>.<cyan>{function}</cyan>"  # 模块名.方法名
                               ":<cyan>{line}</cyan> | "  # 行号
                               "<level>{level}</level>: "  # 等级
                               "<level>{message}</level>",  # 日志内容
                        )
        # 日志写入文件
        self.logger.add(log_path,  # 写入目录指定文件
                        format='{time:YYYYMMDD HH:mm:ss} - '  # 时间
                               "{process.name} | "  # 进程名
                               "{thread.name} | "  # 进程名
                               '{module}.{function}:{line} - {level} -{message}',  # 模块名.方法名:行号
                        encoding='utf-8',
                        retention='7 days',  # 设置历史保留时长
                        backtrace=True,  # 回溯
                        diagnose=True,  # 诊断
                        enqueue=True,  # 异步写入
                        rotation="00:00",  # 每日更新时间
                        # rotation="5kb",  # 切割,设置文件大小,rotation="12:00",rotation="1 week"
                        # filter="my_module"  # 过滤模块
                        # compression="zip"   # 文件压缩
                        )
    def get_logger(self):
        return self.logger

log = Logger().get_logger()

调用的时候在其他Python文件中导入log就可以直接使用,

实例代码:

import uvicorn
from fastapi import FastAPI
from log import log

app = FastAPI()


@app.get("/")
def index():
    log.error("/index")
    return "Hello, World."


if __name__ == '__main__':
    uvicorn.run("test7:app", host='0.0.0.0', port=9999)

输出结果图如下:

f1553727aa894c0d9f09428277e10671.png

上面的结果图可以看出除了loguru日志输出的日志外还有uvicorn输出的日志信息,uvicorn输出的日志和loguru的日志是没有关系的,uvicorn的日志是输出到控制台的他不会输出的日志文件,如果要输出到文件要额外去配置,这样先一个项目就要去维护两个日志,这样对开发和维护就很麻烦,不好统一管理日志,使用要将uvicorn输出的日志全部交给loguru来管理,这样就很方便后期开发和维护。

整合后的代码log.py文件的修改如下:

import os
import sys
import time
import logging
from types import FrameType
from typing import cast
from loguru import logger
from .path_conf import LogPath


class Logger:
    """输出日志到文件和控制台"""

    def __init__(self):
        # 文件的命名
        log_name = f"Fast_{time.strftime('%Y-%m-%d', time.localtime()).replace('-', '_')}.log"
        log_path = os.path.join(LogPath, "Fast_{time:YYYY-MM-DD}.log")
        self.logger = logger
        # 清空所有设置
        self.logger.remove()
        # 判断日志文件夹是否存在,不存则创建
        if not os.path.exists(LogPath):
            os.makedirs(LogPath)
        # 日志输出格式
        formatter = "{time:YYYY-MM-DD HH:mm:ss} | {level}: {message}"
        # 添加控制台输出的格式,sys.stdout为输出到屏幕;关于这些配置还需要自定义请移步官网查看相关参数说明
        self.logger.add(sys.stdout,
                        format="<green>{time:YYYYMMDD HH:mm:ss}</green> | "  # 颜色>时间
                               "{process.name} | "  # 进程名
                               "{thread.name} | "  # 进程名
                               "<cyan>{module}</cyan>.<cyan>{function}</cyan>"  # 模块名.方法名
                               ":<cyan>{line}</cyan> | "  # 行号
                               "<level>{level}</level>: "  # 等级
                               "<level>{message}</level>",  # 日志内容
                        )
        # 日志写入文件
        self.logger.add(log_path,  # 写入目录指定文件
                        format='{time:YYYYMMDD HH:mm:ss} - '  # 时间
                               "{process.name} | "  # 进程名
                               "{thread.name} | "  # 进程名
                               '{module}.{function}:{line} - {level} -{message}',  # 模块名.方法名:行号
                        encoding='utf-8',
                        retention='7 days',  # 设置历史保留时长
                        backtrace=True,  # 回溯
                        diagnose=True,  # 诊断
                        enqueue=True,  # 异步写入
                        rotation="00:00",  # 每日更新时间
                        # rotation="5kb",  # 切割,设置文件大小,rotation="12:00",rotation="1 week"
                        # filter="my_module"  # 过滤模块
                        # compression="zip"   # 文件压缩
                        )

    def init_config(self):
        LOGGER_NAMES = ("uvicorn.asgi", "uvicorn.access", "uvicorn")

        # change handler for default uvicorn logger
        logging.getLogger().handlers = [InterceptHandler()]
        for logger_name in LOGGER_NAMES:
            logging_logger = logging.getLogger(logger_name)
            logging_logger.handlers = [InterceptHandler()]

    def get_logger(self):
        return self.logger


class InterceptHandler(logging.Handler):
    def emit(self, record: logging.LogRecord) -> None:  # pragma: no cover
        # Get corresponding Loguru level if it exists
        try:
            level = logger.level(record.levelname).name
        except ValueError:
            level = str(record.levelno)

        # Find caller from where originated the logged message
        frame, depth = logging.currentframe(), 2
        while frame.f_code.co_filename == logging.__file__:  # noqa: WPS609
            frame = cast(FrameType, frame.f_back)
            depth += 1

        logger.opt(depth=depth, exception=record.exc_info).log(
            level, record.getMessage(),
        )


Loggers = Logger()
log = Loggers.get_logger()

FastApi启动的位置需要修改:

import uvicorn
from fastapi import FastAPI
from log import log, Loggers

app = FastAPI()


@app.get("/")
def index():
    log.error("/index")
    return "Hello, World."


if __name__ == '__main__':
    config = uvicorn.Config("test7:app", host='0.0.0.0', port=9999)
    server = uvicorn.Server(config)
    # 将uvicorn输出的全部让loguru管理
    Loggers.init_config()
    server.run()

运行截图:

a569186fe8154273809202e0ad8ff279.png

上面的FastAPI启动成功信息和访问接口的信息全部都由loguru打印出来了,这样loguru完全管理了FastApi的所有日志信息。这样就能很好的统一管理日志信息

个人博客网站,灵动空间,欢迎访问

  • 9
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
可以使用FastAPI和Jinja2一起创建具有CSS的网站。以下是一些步骤: 1. 首先,确保您已将所需的CSS文件放在正确的位置。例如,您可以将CSS文件放在“static/css”目录中。 2. 在FastAPI应用程序中,使用以下代码来设置Jinja2模板: ```python from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates app = FastAPI() templates = Jinja2Templates(directory="templates") ``` 3. 创建一个Jinja2模板,并在其中引用CSS文件。例如,您可以创建一个名为“index.html”的文件,并在其中引用CSS文件: ```html <!DOCTYPE html> <html> <head> <title>FastAPI + Jinja2</title> <link rel="stylesheet" href="{{ url_for('static', path='/css/style.css') }}"> </head> <body> <h1>FastAPI + Jinja2</h1> <p>Hello, {{ name }}!</p> </body> </html> ``` 4. 在FastAPI应用程序中,创建一个路由方法来呈现Jinja2模板。例如: ```python @app.get("/", response_class=HTMLResponse) async def read_item(request: Request): return templates.TemplateResponse("index.html", {"request": request, "name": "John Doe"}) ``` 在此示例中,我们使用了“TemplateResponse”类来呈现Jinja2模板。我们还将“request”和“name”作为参数传递给模板。 5. 最后,在FastAPI应用程序中,使用以下代码来指定包含CSS文件的目录: ```python app.mount("/static", StaticFiles(directory="static"), name="static") ``` 在此示例中,我们使用“StaticFiles”类来指定包含CSS文件的目录。我们还将此目录挂载到FastAPI应用程序的“/static”路径上。 这样,您就可以在FastAPI应用程序中使用Jinja2模板和CSS文件来创建具有样式的网站了。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值