Joh*_*ohn 5 python wsgi werkzeug flask
这是一个重现该问题的复制粘贴示例。
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。我假设DispatcherMiddlewareorrun_simple在记录异常之前以某种方式捕获异常。如果我仅app使用app.run()错误日志运行实例,则效果很好。
当 时,不会调用正常的异常处理程序app.debug = True。app.py查看Flask中的代码:
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:显式启用或禁用异常的传播。如果未设置或显式设置为 None ,则如果 TESTING 或DEBUG 为true ,则隐式为 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
| 归档时间: | 
 | 
| 查看次数: | 5592 次 | 
| 最近记录: |