所以这是一个复制粘贴示例,可以重现问题。
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
文件中。我假设DispatcherMiddleware
或run_simple
以某种方式捕获异常,然后才能记录它。如果我使用app
仅运行app.run()
实例,则错误记录工作正常。
答案 0 :(得分:1)
我找到了gist,其中谈到了登录烧瓶。 andyxning的评论(2015年4月18日评论)提到了这一点 - if app.debug is True then all log level above DEBUG will be logged to stderr(StreamHandler)
。
评论还有一个指向flask/logging.py源代码的链接。 create_logger
方法创建DebugHandler
的实例,该实例继承自StreamHandler
类。
如果您打印app.logger.handlers
,则可以看到它的对象为flask.logging.DebugHandler
。
print app.logger.handlers
[<flask.logging.DebugHandler object at 0x110315090>]
这个DebugHandler可能在app.debug is set to true
时使用,因此堆栈跟踪会在控制台上打印出来。
希望这就是你要找的东西。
答案 1 :(得分:1)
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:显式启用或禁用异常传播。如果没有设置或明确设置为无,如果TESTING或 DEBUG为真,则隐式为真。
所以,我设法让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