Я создал базовое приложение Flask и зарегистрировал собственный обработчик ошибок для определенного пользовательского типа исключения. Однако когда этот тип исключения генерируется и передается в стек, Flask не использует указанный пользовательский обработчик ошибок.
Я создал второй обработчик ошибок с базовым типом исключения, который успешно перехватывает ошибку. Присутствие базового обработчика исключений не влияет на способность настраиваемого обработчика ошибок отлавливать ошибки. Если базовый обработчик не присутствует, ошибка пузырится вплоть до страницы Flask 500 по умолчанию.
Я также сделал print(srv.error_handler_spec)
, и кажется, что обработчик ошибок успешно регистрируется.
Вот основная часть srv.py
, точка входа для моего приложения Flask
from flask import Flask, request
from flask import jsonify
srv = Flask(__name__)
class APIError(Exception):
def __init__(self, message, status_code=500):
Exception.__init__(self)
self.message = message
self.status_code = status_code
def log_error(self):
logging.error(f"API error: {self.to_json()}")
def to_dict(self):
return {"message": self.message, "status_code": self.status_code}
@srv.errorhandler(Exception)
def exception_handler(e: Exception):
response = jsonify(
{"message": f"unhandled exception encountered", "status_code": 500}
)
logging.error(f"unhandled exception encountered. type: {e.__class__}")
response.status_code = 500
return response
@srv.errorhandler(APIError)
def api_error_handler(e: APIError):
response = jsonify(e.to_dict())
response.status_code = e.status_code
return response
print(srv.error_handler_spec)
@srv.route("/", methods=["GET"])
def hello_world():
return "hello world"
@srv.route("/error", methods=["GET"])
def error():
raise APIError("generic error", status_code=400)
Это вывод журнала из Flask при скручивании /error
[32mapp_1 |[0m {None: {None: {<class 'Exception'>: <function exception_handler at 0x7f211b8a5598>, <class 'srv.APIError'>: <function api_error_handler at 0x7f211b8a5620>}}}
[32mapp_1 |[0m {None: {None: {<class 'Exception'>: <function exception_handler at 0x7f211b8a5e18>, <class '__main__.APIError'>: <function api_error_handler at 0x7f211b8a5ea0>}}}
[32mapp_1 |[0m * Serving Flask app "srv" (lazy loading)
[32mapp_1 |[0m * Environment: production
[32mapp_1 |[0m WARNING: Do not use the development server in a production environment.
[32mapp_1 |[0m Use a production WSGI server instead.
[32mapp_1 |[0m * Debug mode: off
[32mapp_1 |[0m * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
[32mapp_1 |[0m ERROR:root:unhandled exception encountered. type: <class 'srv.APIError'>
[32mapp_1 |[0m 172.27.0.5 - - [04/May/2019 06:52:47] "POST /api/user/create HTTP/1.1" 500 -
[32mapp_1 |[0m INFO:werkzeug:172.27.0.5 - - [04/May/2019 06:52:47] "POST /api/user/create HTTP/1.1" 500 -
[32mapp_1 |[0m 172.27.0.5 - - [04/May/2019 06:52:47] "GET /error HTTP/1.1" 400 -
[32mapp_1 |[0m INFO:werkzeug:172.27.0.5 - - [04/May/2019 06:52:47] "GET /error HTTP/1.1" 400 -
Как видно из строки журнала ERROR:root:unhandled exception encountered. type: <class 'srv.APIError'>
, он использует общий обработчик Exception
, а не пользовательский для APIError
.
Ожидаемое поведение - вместо этого Flask вместо этого использует пользовательский обработчик ошибок и вообще не печатает ни одной строки журнала.
Для записи результаты из curl
согласуются с общим обработчиком ошибок, возвращающим ответ. Это определенно не проблема с универсальным обработчиком, перекрывающим более специфический обработчик. (Хотя это также было бы ошибочным согласно документации Flask).
Что дает?