python - 为什么在使用 werkzeug 运行 Flask 应用程序时日志记录不起作用?

标签 python flask wsgi werkzeug

所以这是一个重现问题的复制粘贴示例。

import logging

from flask import Flask
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware

def app_builder(app_name, log_file):

    app = Flask(app_name)
    app.debug = True

    handler = logging.FileHandler(log_file)
    handler.setLevel(logging.DEBUG)
    app.logger.addHandler(handler)

    return app

def _simple(env, resp):
    resp(b'200 OK', [(b'Content-Type', b'text/plain')])
    return [b'root']

if __name__ == "__main__":

    app = app_builder(app_name='app', log_file='app.log')

    @app.route('/')
    def index():
        return '<a href="/app/error">click for error</a>'

    @app.route('/error')
    def error():
        1/0
        return 'error page'

    app2 = app_builder(app_name='app2', log_file='app2.log')

    @app2.route('/')
    def index():
        return 'you are getting responses from app2'

    app.debug = True
    app2.debug = True

    application = DispatcherMiddleware(_simple, {
        '/app':     app,
        '/app2':    app2
        })

    run_simple(hostname='localhost',
               port=5000,
               application=application,
               use_reloader=True,
               use_debugger=True)

要显示错误,请导航至 http://localhost:5000/app/error ,我想知道为什么堆栈跟踪没有出现在 app.log 中文件。我假设 DispatcherMiddlewarerun_simple在记录异常之前以某种方式捕获异常。如果我只运行 app使用 app.run() 的实例错误记录工作正常。

最佳答案

app.debug = True 时,不会调用正常的异常处理程序。看着 在 Flask 中的 app.py 代码中:

def log_exception(self, exc_info):
    """Logs an exception.  This is called by :meth:`handle_exception`
    if debugging is disabled and right before the handler is called.
    ^^^^^^^^^^^^^^^^^^^^^^^^
    The default implementation logs the exception as error on the
    :attr:`logger`.

确实,当设置 app.debug = True 时,异常传播被设置 显式为 True,这会阻止调用 log_exception。这是文档的摘录(重点是我的):

PROPAGATE_EXCEPTIONS: explicitly enable or disable the propagation of exceptions. If not set or explicitly set to None this is implicitly true if either TESTING or DEBUG is true.

所以,我设法让 werkzeug 调试和日志记录工作愉快 连同一点点调整和以下代码:

import logging

from flask import Flask
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware
## NEW CODE HERE
import functools
from flask._compat import reraise

def my_log_exception(exc_info, original_log_exception=None):
    original_log_exception(exc_info)
    exc_type, exc, tb = exc_info
    # re-raise for werkzeug
    reraise(exc_type, exc, tb)
## 

def app_builder(app_name, log_file):
    app = Flask(app_name)
    app.debug = True
    app.config.update(PROPAGATE_EXCEPTIONS=False)

    handler = logging.FileHandler(log_file)
    handler.setLevel(logging.DEBUG)
    app.logger.addHandler(handler)

    ## NEW CODE
    app.log_exception = functools.partial(my_log_exception,  original_log_exception=app.log_exception)
    ##

    return app

# rest of your code is unchanged

关于python - 为什么在使用 werkzeug 运行 Flask 应用程序时日志记录不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39646236/

相关文章:

python:解析带文件上传和附加参数的 HTTP POST 请求

python - 在 Django 和 Apache 中使用 WSGI 时如何修复 "Timeout when reading response headers from daemon process"错误

python - 通过Windows Task Scheduler 调用python 脚本时,如何正确导入用户定义的模块(包)?

python - 如何使用 tkinter 调整此图像的大小?

javascript - jquery .prop() 不适用于带有复选框的下拉菜单

python - 使用 flask-aiohttp 的异步子进程

python - 如何确定模块名称是否是 python 标准库的一部分

python - 我用于更新 ID = 整数的 MySQL 表的 Python 代码有什么问题?

python - 是否可以克隆请求以供以后使用?

django - 如何将 Web 套接字与 django wsgi 集成