2016-09-22 10 views
4

これは、問題を再現するコピー貼り付けの例です。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ファイルに表示されない理由を知りたいです。私は、DispatcherMiddlewareまたはrun_simpleが何らかの形でログに記録される前に例外をキャッチしていると仮定します。 app.run()を使用してappインスタンスのみを実行すると、エラーログが正常に動作します。

+0

あなたは、このような[PuDB](HTTPSなどのデバッガで実行してみました://pypi.python.org/pypi/pudb)?エラールートにブレークポイントをドロップし、コールに従って、エラーの発生場所を確認します。 –

+0

ログに書き留めるように指示する必要があります。 'app.logger.debug(" My error ")' – iScrE4m

+0

@ iScrE4mしかし、なぜそれをする必要があるのですか?werkzeugは例外をログに記録しません(app.run () ')? – John

答えて

1

app.debug = Trueの場合、通常の例外ハンドラは呼び出されません。フラスコ内のapp.pyのコードで を探している相手:app.debug = Trueを設定するときに

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`. 

実際、例外の伝播が呼び出されるlog_exceptionを防止する、明示的にTrueに に設定されています。ここでは、ドキュメントの抜粋です(重点は私です)。

PROPAGATE_EXCEPTIONS:例外の伝播を明示的に有効または無効にします。設定されていない場合、または明示的に[なし]に設定されている場合は、の場合は、暗黙的には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 
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メソッドは、StreamHandlerクラスを継承するDebugHandlerのインスタンスを作成します。

app.logger.handlersを印刷すると、オブジェクトがflask.logging.DebugHandlerであることがわかります。

print app.logger.handlers 
[<flask.logging.DebugHandler object at 0x110315090>] 

このDebugHandlerはおそらく使用されている場合app.debug is set to trueので、スタックトレースがコンソールに印刷されます。

これがあなたが探しているものです。

関連する問題