• flask基础之配置日志logger(十一)


    前言

    python有默认的日志配置,但是对于业务开发来说一般需要配置自己的日志输出方式,同时各种框架也继承了日志相关的内容。下面记录一下celery和flask框架中自带的logger使用方法。

    flask使用logger

    flask中的app对象自带了logger方法,其本质上是在python内置的logging模块上进行封装使用,其调用的方式为:

    from flask import current_app
    
    current_app.logger.error('this is a error')
    current_app.logger.info('this is a info')
    current_app.logger.warning('this is a wraning')
    current_app.logger.debug('this is a debug')
    

    配置方法

    日志的配置方法有多种,和python配置日志的方式是一样的。

    可参考:python日志配置logger

    • 通过字典配置
    #logging.py
    logger_dict = {
        'version': 1, # 该配置写法固定
        'formatters': { # 设置输出格式
            'default': {'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',}
        },
        # 设置处理器
        'handlers': {
            'wsgi': {
                'class': 'logging.StreamHandler',
                'stream': 'ext://sys.stdout',
                'formatter': 'default',
                'level': 'DEBUG'
                    }},
        # 设置root日志对象配置
        'root': {
            'level': 'INFO',
            'handlers': ['wsgi']
        },
        # 设置其他日志对象配置
        'loggers': {
            'test':
                {'level': 'DEBUG',
                 'handlers':['wsgi'],
                 'propagate':0}
        }
    }
    
    • 源码分析

    flask的logger其实也是通过python的logging模块创建logger对象得到的,源码为:

    # logging.py
    from logging import getLogger, getLoggerClass
    def create_logger(app):
        ...
        # 创建一个调试模式下的日志处理器,级别为debug
        debug_handler = DebugHandler()
        debug_handler.setLevel(DEBUG)
        debug_handler.setFormatter(Formatter(DEBUG_LOG_FORMAT))
        # 创建一个运行过程的日志处理器,级别为error
        prod_handler = ProductionHandler(_proxy_stream)
        prod_handler.setLevel(ERROR)
        prod_handler.setFormatter(Formatter(PROD_LOG_FORMAT))
        # 获取应用的名字,即app = Flask(app.name)传入的参数名,然后创建一个logger对象
        logger = getLogger(app.logger_name)
        # 先清空以前所有的处理器
        del logger.handlers[:]
        logger.__class__ = DebugLogger
        # 加入新的处理器
        logger.addHandler(debug_handler)
        logger.addHandler(prod_handler)
    
        # 默认情况下不继承
        logger.propagate = False
        return logger
    

    当程序调用current_app.logger时,会得到create_logger函数返回的logger对象,如果我们开启的是调试模式,会使用debug_handler处理器;如果是非调试模式使用的是ProductionHandler处理器,日志的输出格式为:

    # 调试模式格式
    DEBUG_LOG_FORMAT = (
        '-' * 80 + '
    ' +
        '%(levelname)s in %(module)s [%(pathname)s:%(lineno)d]:
    ' +
        '%(message)s
    ' +
        '-' * 80
    )
    # 非调试模式格式
    PROD_LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
    

    此外我们开发程序时可以看到除了我们调用current_app.logger产生的日志信息外,还有flask默认的日志信息,这个默认的日志输出我们是可以通过配置日志文件来修改的,但是current_app.logger产生的日志信息的格式是固定的,如果不满足我们的要求的话就需要手动创建logger对象来使用。

    细节

    我们加载日志文件的时候应该尽可能的早,避免在调用过一次app.logger之后才加载日志配置,所以最好在app被创建之前就加载日志配置文件。

    # app.py
    logging.config.fileConfig(Config.FILEPATH)
    app = Flask(__name__)
    

    在celery中使用logger

    celery也封装了logger使用方法:

    from celery.utils.log import get_task_logger
    # 创建一个logger对象
    logger = get_task_logger('name')
    

    celery的logger调用的仍然是logging模块的logger.

    # get_task_logger函数调用了get_logger函数
    # 传入一个字符串获取一个logger对象
    def get_logger(logger):
        """Get logger by name."""
        # 判断该参数是不是字符串,是就获取一个logger对象
        if isinstance(logger, string_t):
            logger = logging.getLogger(logger)
        # 没有处理器就添加NullHandler处理器
        if not logger.handlers:
            logger.addHandler(logging.NullHandler())
        return logger
    
    • 其相关的配置可以在celery的配置文件中设置;
    # 在4.0版本后改成了小写,但是原来的还没有弃用
    CELERYD_HIJACK_ROOT_LOGGER :默认true,先前所有的logger的配置都会失效,可以通过设置false禁用定制自己的日志处理程序;
    CELERYD_LOG_COLOR :是否开启不同级别的颜色标记,默认开启;
    CELERYD_LOG_FORMAT :设置celery全局的日志格式;默认格式:"[%(asctime)s: %(levelname)s/%(processName)s] %(message)s"
    CELERYD_TASK_LOG_FORMAT:设置任务日志格式,默认:"[%(asctime)s: %(levelname)s/%(processName)s [%(task_name)s(%(task_id)s)] %(message)s"
    CELERY_REDIRECT_STDOUTS:设置标准输入输出重定向到当前的处理器,默认为 true
    CELERY_REDIRECT_STDOUTS_LEVEL:设定标准输入输出重定向到当前的处理器日志的输出级别;即指定使用print()输出的是什么级别的日志记录;默认wraning;
    

    注意:

    1. 由于celery的运行是独立的,在flask中定义的logger对象的配置在celery的程序中是失效的,必须使用get_task_logger创建logger;

    2. 指定celery日志的输出等级,通过启动时用--loglevel参数来指定;

    参考

  • 相关阅读:
    使用Python创建自己的Instagram滤镜
    TensorFlow v2.0实现逻辑斯谛回归
    自动驾驶研究回顾:CVPR 2019摘要
    dp cf 20190613
    简单搜索 kuangbin C D
    树形dp compare E
    区间dp E
    Codeforces Round #564 (Div. 2)
    网络流 + 欧拉回路 = B
    网络流 A
  • 原文地址:https://www.cnblogs.com/cwp-bg/p/8946394.html
Copyright © 2020-2023  润新知