web-dev-qa-db-ja.com

例外のグローバルエラーハンドラー

応答を汎用JSON応答に変更できるグローバルなキャッチオールエラーハンドラーを追加する方法はありますか?

_got_request_exception_信号は使用できません。応答を変更することが許可されていないためです( http://flask.pocoo.org/docs/0.10/signals/ )。

対照的に、すべてのシグナルハンドラは未定義の順序で実行され、データを変更しません。

_app.handle_exception_関数は、内部APIのように感じるため、ラップしない方がよいでしょう。私は次のようなことをしていると思います:

_ @app.errorhandler()
 def handle_global_error(e):
     return "Global error"
_

errorhandlerはパラメーターを受け取らないことに注意してください。つまり、特定のエラーハンドラーが接続されていないすべての例外/ステータスコードをキャッチします。 errorhandler(500)またはerrorhandler(Exception)を使用して例外をキャッチできることは知っていますが、たとえばabort(409)を実行すると、HTML応答が返されます。

39
joscarsson

@app.errorhandler(Exception)を使用できます:

デモ(HTTPExceptionチェックにより、ステータスコードが確実に保持されます):

from flask import Flask, abort, jsonify
from werkzeug.exceptions import HTTPException

app = Flask('test')

@app.errorhandler(Exception)
def handle_error(e):
    code = 500
    if isinstance(e, HTTPException):
        code = e.code
    return jsonify(error=str(e)), code

@app.route('/')
def index():
    abort(409)

app.run(port=1234)

出力:

$ http get http://127.0.0.1:1234/
HTTP/1.0 409 CONFLICT
Content-Length: 31
Content-Type: application/json
Date: Sun, 29 Mar 2015 17:06:54 GMT
Server: Werkzeug/0.10.1 Python/3.4.3

{
    "error": "409: Conflict"
}

$ http get http://127.0.0.1:1234/notfound
HTTP/1.0 404 NOT FOUND
Content-Length: 32
Content-Type: application/json
Date: Sun, 29 Mar 2015 17:06:58 GMT
Server: Werkzeug/0.10.1 Python/3.4.3

{
    "error": "404: Not Found"
}

Flask(JSONも返すように)からのデフォルトのHTML例外もオーバーライドする場合は、app.runの前に次を追加します。

from werkzeug.exceptions import default_exceptions
for ex in default_exceptions:
    app.register_error_handler(ex, handle_error)

古いFlaskバージョン(<= 0.10.1、つまり現時点ではgit/master以外のバージョン)の場合、次のコードをアプリケーションに追加してHTTPエラーを明示的に登録します。

from werkzeug import HTTP_STATUS_CODES
for code in HTTP_STATUS_CODES:
    app.register_error_handler(code, handle_error)
46
ThiefMaster

これはFlask 0.12と互換性があり、問題に対する非常に優れたソリューションです(JSONまたはその他の形式でエラーを表示できます)

from functools import wraps
from flask import Flask, redirect, jsonify
app = Flask(__name__)

def get_http_exception_handler(app):
    """Overrides the default http exception handler to return JSON."""
    handle_http_exception = app.handle_http_exception
    @wraps(handle_http_exception)
    def ret_val(exception):
        exc = handle_http_exception(exception)    
        return jsonify({'code':exc.code, 'message':exc.description}), exc.code
    return ret_val

# Override the HTTP exception handler.
app.handle_http_exception = get_http_exception_handler(app)

https://github.com/pallets/flask/issues/671#issuecomment-12746738

10
lol

エレガントとはほど遠いが、以下はHTTPExceptionのすべてのサブクラスを単一のエラーハンドラに結び付けるために機能する:

from flask import jsonify
from werkzeug.exceptions import HTTPException

def handle_error(error):
    code = 500
    if isinstance(error, HTTPException):
        code = error.code
    return jsonify(error='error', code=code)

for cls in HTTPException.__subclasses__():
    app.register_error_handler(cls, handle_error)
6
bwind

これをFlask> = 0.12で実装するよりクリーンな方法は、Werkzeug例外ごとにハンドラーを明示的に登録することです。

from flask import jsonify
from werkzeug.exceptions import HTTPException, default_exceptions

app = Flask('test')

def handle_error(error):
    code = 500
    if isinstance(error, HTTPException):
        code = error.code
    return jsonify(error='error', code=code)

for exc in default_exceptions:
    app.register_error_handler(exc, handle_error)
2
nfvs

REST api のプレーン(非HTML)エラーページに基づく

コードをまったく変更せずにjsonを返したいので、コードの先頭に次を追加しました

@app.errorhandler(500)
def error_500(exception):
    return jsonify({"error": str(exception)}), 500, {'Content-Type': 'application/json'}

@app.errorhandler(400)
def error_400(exception):
    return jsonify({"error": str(exception)}), 400, {'Content-Type': 'application/json'}
0
julianalimin

例外が機能しない場合は、app.register_error_handler(またはapp.errorhandler非装飾的な方法で)

ソース: https://github.com/pallets/flask/issues/1837

0
Suresh Ganta