【问题标题】:Flask duplicate logs after importing fbprophet导入 fbprophet 后烧瓶重复日志
【发布时间】:2019-06-05 13:37:36
【问题描述】:

我想通过在我需要登录的每个文件中调用logging.getLogger('myapi') 来在我的 Flask 应用程序中使用日志记录。

应该有一个地方来定义这个“全局”应用程序记录器的处理程序和格式。这可行,但 Flask 也不断地以默认格式记录自己的日志。这些日志仅在我导入库fbprophet 时存在。我想阻止 Flask 记录这些额外的、未格式化的、重复的日志。

(Flask 还有一个werkzeug 记录器,很好,可以留。)

代码

import sys
import logging
import fbprophet
from flask import Flask, jsonify
from werkzeug.serving import run_simple

# Set up my custom global logger
log = logging.getLogger('myapi')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(logging.Formatter('*** %(asctime)s %(levelname)s %(message)s'))
log.addHandler(handler)
log.setLevel(logging.DEBUG)

def create_app(config={}):
    ''' Application factory to create and configure the app '''
    app = Flask('myapi', instance_relative_config=False)
    app.config.from_mapping(config)

    log.info('TEST INFO')
    log.debug('TEST DEBUG')

    @app.route('/health')
    def health():
        log.info('Health OK')
        return 'OK'

    return app

if __name__ == '__main__':
    dev_config = {'SECRET_KEY': 'dev', 'DEBUG': False}
    app = create_app(dev_config)
    run_simple('localhost', 5000, app)

输出:

我希望看到以*** 为前缀的日志。以LEVEL 开头的只有在我导入facebook 先知时才会出现。

* Serving Flask app "main.py" (lazy loading)
* Environment: development
* Debug mode: on
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
*** 2019-06-05 14:17:56,702 INFO TEST INFO          # good log
INFO:myapi:TEST INFO                                # bad dupe log
*** 2019-06-05 14:17:56,702 DEBUG TEST DEBUG
DEBUG:myapi:TEST DEBUG
*** 2019-06-05 14:17:56,703 INFO TEST INFO
INFO:myapi:TEST INFO
*** 2019-06-05 14:17:56,703 DEBUG TEST DEBUG
DEBUG:myapi:TEST DEBUG
*** 2019-06-05 14:18:10,405 INFO Health OK
INFO:myapi:Health OK
127.0.0.1 - - [05/Jun/2019 14:18:10] "GET /health HTTP/1.1" 200 -               # good werkzeug api log
INFO:werkzeug:127.0.0.1 - - [05/Jun/2019 14:18:10] "GET /health HTTP/1.1" 200 - # bad dupe log

更多解释:

我也尝试过设置应用的记录器,但我不想从其他模块调用current_app.logger

我尝试使用 logging.getLogger('flask.app').handlers.clear() 禁用 Flask 的记录器,但这也不起作用。

导入fbprophet 时,我收到以下控制台错误(来自先知):

ERROR:fbprophet:Importing matplotlib failed. Plotting will not work.
ERROR:fbprophet:Importing matplotlib failed. Plotting will not work.
*** 2019-06-05 14:29:06,488 INFO TEST INFO
INFO:myapi:TEST INFO

我认为这可能会导致问题,因此我修复了错误following this。但 Flask 仍在记录额外的日志。

import plotly
import matplotlib as mpl
mpl.use('TkAgg')
import fbprophet

总结:

在 Flask 中寻找格式化的全局日志,没有重复的日志。我只需要我的全局 logging.getLogger('myapi')werkzeug API 日志。

【问题讨论】:

    标签: python logging flask facebook-prophet


    【解决方案1】:

    我也遇到过同样的问题,花了好几个小时才解决。实际上它甚至与 Flask 无关(我在几个小时后发现了这一点)。

    即使在一个简单的脚本中,您的处理程序中也会有重复的日志。

    唯一的工作解决方案似乎是在您自己的处理程序中添加:logger.propagate = False。这将防止将日志传递给更高级别(祖先)记录器的处理程序,即由 Prophet 创建的记录器(即使我没有看到这个层次结构的确切位置)。

    在这个答案中找到:https://stackoverflow.com/a/55877763/3615718

    【讨论】:

      【解决方案2】:

      您可以搜索所有已注册的记录器并根据需要更改其设置。听起来fbprophet 可能正在设置它自己的logger 实例,所以如果您执行以下操作,希望它会设置为您想要的级别:

      for logger_name in logging.root.manager.loggerDict:
          print(f"found a logger:{logger_name}")
          logger = logging.getLogger(logger_name)
          logger.setLevel(logging.ERROR)
      
          if logger_name == 'myapi':
              logger.setLevel(logging.INFO)
      

      【讨论】:

      • 虽然它正在复制通用日志,但这可能不是解决方案。只需打印 logging.root.manager.loggerDict 即可获得有关这些库设置内容的更多信息,或者您可以查看它们的日志记录源代码。
      • 好主意!查看所有工作中的记录器很有用,但不幸的是这不起作用 - 即使所有记录器都设置为 ERROR 级别,我们仍然看到重复的 Flask 日志......嗯
      • @repoleved - 看起来这可能是您问题的答案:stackoverflow.com/a/44049484/3945895
      • 另一个好发现 :) 这将删除我们想要的格式化全局记录器并留下丑陋的 Flask 记录器(即只留下 INFO:myapi:TEST INFO 日志)即使在 loggerDict 中也没有命名为 Flask!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 1970-01-01
      • 2019-01-12
      相关资源
      最近更新 更多