Flask 3.x log全域配置(包含pytest)

发布时间:2024年01月19日

最近使用到flask3.x,配置了全域的log,这边记录下

首先需要创建logging的配置文件,我是放在项目根目录的,

Logging 配置?

logging.json?

{
    "version": 1,  # 配置文件版本号

    "formatters": {
        "default": {
            "format": "[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
            # 默认的日志格式,包含时间、日志级别、模块和消息
        }
    },

    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            # 日志处理器的类,将日志输出到控制台
            "level": "DEBUG",  # 控制台处理器的日志级别为 DEBUG
            "formatter": "default",  # 使用上面定义的 "default" 格式化器
            "stream": "ext://sys.stdout"  # 输出流为标准输出流
        },

        "file": {
            "class": "logging.handlers.RotatingFileHandler",
            # 日志处理器的类,将日志输出到文件
            "level": "INFO",  # 文件处理器的日志级别为 INFO
            "formatter": "default",  # 使用上面定义的 "default" 格式化器
            "filename": "logs/log",  # 日志文件的名称(logs 目录下的 log 文件)
            "maxBytes": 10485760,  # 每个日志文件的最大大小为 10 MB
            "backupCount": 20,  # 保留最近 20 个日志文件备份
            "encoding": "utf8"  # 使用 UTF-8 编码
        }
    },

    "root": {
        "level": "DEBUG",  # 根日志记录器的级别为 DEBUG
        "handlers": ["console", "file"]
        # 根日志记录器使用上面定义的 "console" 和 "file" 两个处理器
    }
}

application.py

然后在application.py中加载logging.json,并且用dictConfig加载到logging的配置中。

这里使用../logging.json是因为我的logging.json是在application.py的上一层,具体放的值,要参考具体的路径来配置

"""Application module."""

from logging.handlers import RotatingFileHandler
import os
from flask import Flask
from flask_bootstrap import Bootstrap
from main.web.route.views import xxx_bp
from main.containers import Container
from logging.config import dictConfig
import json

def create_app() -> Flask:

    app = Flask(__name__,template_folder='webapp/templates',static_folder='webapp/content')
    container = Container()
    init_config_log()
    app.register_blueprint(xxx_bp,url_prefix='/xxx')
    
    app.container = container
    bootstrap = Bootstrap()
    bootstrap.init_app(app)

    return app

def init_config_log() -> None:
    with open(os.path.join(os.path.dirname(__file__), "../logging.json")) as f:
        logging_config = json.load(f)
    dictConfig(logging_config)


使用的时候就直接使用current_app.logger打印就可以了?


from flask import current_app
class xxxxxService:

    def __init__(self,...) -> None:
        ...

    def test_log(self) -> None:
        current_app.logger.error("Log something....")
       

?还有记得根据你logging.json配置的filename建立他的父文件夹,对于我的配置就是建立logs文件夹,否则启动项目的时候就会报错:

?并且所有的log也会被记录到配置的filename的文件里面。

pytest

pytest中有自己独立的log,但是如果加载了app,类似于这种

import datetime
import pytest
from main.application import create_app
from flask import current_app

@pytest.fixture
def app():
    app = create_app()
    app.config.update({
        "TESTING": True,
    })
    yield app

@pytest.fixture
def xxxx_service(app):
    with app.app_context():
        xxxx_repo=xxxxRepositoryImpl()
        yield xxxService(xxxx_repo=xxxx_repo)
        # yield UserService(user_repository=user_repo,session_factory=db.session)
        

def test_create_user(xxxx_service):
    current_app.logger.info("Log Something")
    xxx=xxxx_service.xx_function()
    assert xxx == "some value"
    
      

就会导致Flask应用程序和pytest都使用了logging模块,但是它们的log配置是独立的,不会相互覆盖。当在Flask中配置了log后,Flask会创建一个名为flask.app的logger对象,并将其添加到logging模块的logger列表中。当在pytest中使用log对象时,您实际上是使用了logging模块的root logger对象,它是默认的logger对象。由于Flask的logger对象的级别高于root logger对象的级别,所以Flask的logger对象会拦截root logger对象的日志消息,导致pytest中的log不打印。

所以呢,我们就统一使用current_app.logger,这种方式打印log。

但是这样会有一个问题,log会被正常记录,也会被放在tests/${filename}中(因为是test中会生成独立的${filename},记得也要提前创建父文件夹),但是console中没有log打印。
这种情况下,就需要修改我们的pytest.ini,如果没有的话,就需要在根目录中新建一个,
这里面的配置是显示

pytest.ini

[pytest]
addopts = -s
#addopts 是一个配置项,用于指定传递给 pytest 的额外命令行选项。
#-s 是 pytest 的一个命令行选项,表示禁用输出捕获,允许测试中的 print 语句将输出直接打印到控制台。
#因此,这个配置告诉 pytest 在运行时使用 -s 选项,使得测试中的输出能够直接显示在终端上,而不是被 #pytest 捕获并隐藏。这在调试和查看详细信息时很有用。?

?加上这个之后,print也会被显示在console,当然也包括我们的log。

之后就可以运行pytest了,不管是我们业务代码中的log,还是test中的log,都会根据我们log的配置打印在console里面,也会记录到test/${filename}中。

文章来源:https://blog.csdn.net/Damien_J_Scott/article/details/135700170
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。