Глобальный обработчик ошибок для любого исключения
есть ли способ добавить глобальный обработчик ошибок catch-all, в котором я могу изменить ответ на общий ответ JSON?
Я не могу использовать got_request_exception
сигнал, так как не разрешается изменять ответ (http://flask.pocoo.org/docs/0.10/signals/).
напротив, все обработчики сигналов выполняются в неопределенном порядке и не изменяют никаких данных.
Я бы предпочел не накручивайте
5 ответов
можно использовать @app.errorhandler(Exception)
:
Demo (проверка 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"
}
если вы также хотите переопределить исключения HTML по умолчанию из Flask (чтобы они также возвращали JSON), добавьте следующее Перед app.run
:
from werkzeug.exceptions import default_exceptions
for ex in default_exceptions:
app.register_error_handler(ex, handle_error)
для более старых версий колбы (
from werkzeug import HTTP_STATUS_CODES
for code in HTTP_STATUS_CODES:
app.register_error_handler(code, handle_error)
это колба 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
далеко не элегантный, но следующие работы для связывания всех подклассов 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)
Если исключения не работают, вы можете попробовать app.register_error_handler (или использовать app.файле errorhandler не в стиле декоратора)
более чистым способом реализовать это в 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, error_handler)