webentwicklung-frage-antwort-db.com.de

Globaler Fehlerbehandler für alle Ausnahmen

Gibt es eine Möglichkeit, einen globalen Catch-All-Error-Handler hinzuzufügen, mit dem ich die Antwort in eine generische JSON-Antwort ändern kann?

Ich kann das got_request_exception - Signal nicht verwenden, da die Antwort nicht geändert werden darf ( http://flask.pocoo.org/docs/0.10/signals/ ).

Im Gegensatz dazu werden alle Signalhandler in undefinierter Reihenfolge ausgeführt und modifizieren keine Daten.

Ich würde es vorziehen, die app.handle_exception - Funktion nicht zu umbrechen, da sich das wie eine interne API anfühlt. Ich schätze, ich bin auf etwas aus wie:

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

Beachten Sie, dass errorhandler keine Parameter akzeptiert. Dies bedeutet, dass alle Ausnahmen/Statuscodes erfasst werden, an die kein spezieller Fehlerhandler angehängt ist. Ich weiß, dass ich errorhandler(500) oder errorhandler(Exception) verwenden kann, um Ausnahmen abzufangen, aber wenn ich zum Beispiel abort(409) tue, wird trotzdem eine HTML-Antwort zurückgegeben.

39
joscarsson

Sie können @app.errorhandler(Exception) verwenden:

Demo (die HTTPException-Prüfung stellt sicher, dass der Statuscode erhalten bleibt):

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)

Ausgabe:

$ 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"
}

Wenn Sie auch die Standard-HTML-Ausnahmen von Flask (damit sie auch JSON zurückgeben) überschreiben möchten, fügen Sie Folgendes vor app.run:

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

Fügen Sie für ältere Flask Versionen (<= 0.10.1, d. H. Derzeit alle Nicht-Git/Master-Versionen) der Anwendung den folgenden Code hinzu, um die HTTP-Fehler explizit zu registrieren:

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

Dies ist Flask 0.12 kompatibel und eine sehr gute Lösung für das Problem (es erlaubt einem, Fehler in JSON oder einem anderen Format zu rendern)

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

Das ist alles andere als elegant, aber das Folgende funktioniert, um alle Unterklassen von HTTPException an einen einzigen Fehlerbehandler zu binden:

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

Eine einfachere Möglichkeit, dies in Flask> = 0.12 zu implementieren, besteht darin, den Handler für jede Werkzeug-Ausnahme explizit zu registrieren:

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

Basierend auf Plain (non-HTML) -Fehlerseiten in REST api

Ich wollte json zurückgeben, ohne meinen Code zu ändern, deshalb habe ich das Folgende oben in meinen Code eingefügt

@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

Wenn die Ausnahmen nicht funktionieren, können Sie versuchen, app.register_error_handler (oder verwenden Sie app.errorhandler nicht dekorativ)

Quelle: https://github.com/pallets/flask/issues/1837

0
Suresh Ganta