为什么我的 Flask 错误处理程序没有被调用?
Why is my Flask error handler not being called?
我正在尝试在 Flask 1.0.2 和 Flask-RESTful 0.3.7 中创建自定义错误处理程序,使用“Implementing API Exceptions" page. (Flask-RESTful has its own way of creating custom error messages”中的指南,但因为它似乎为了有办法在异常发生时接受自定义的错误消息,我正在尝试改用 vanilla Flask 方法。)
from flask import Flask, jsonify
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
#########################################
class MyGenericException(Exception):
status_code = 500
def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
@app.errorhandler(MyGenericException)
def handle_generic_error(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response
#########################################
class TestMe(Resource):
def get(self):
raise MyGenericException('A generic error', status_code=501)
api.add_resource(TestMe, '/testme', endpoint='TestMe')
#########################################
if __name__ == '__main__':
app.run(debug=False)
仅调用 http://127.0.0.1:5000/testme returns 一条通用的“500 内部服务器错误”消息,而不是带有我的自定义错误文本的 501 错误。似乎 MyGenericException
被正确提升,但 Flask 似乎忽略了它。
[2019-05-08 17:09:18,409] ERROR in app: Exception on /testme [GET]
Traceback (most recent call last):
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask_restful\__init__.py", line 458, in wrapper
resp = resource(*args, **kwargs)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask_restful\__init__.py", line 573, in dispatch_request
resp = meth(*args, **kwargs)
File "C:/Users/testuser/Documents/PyCharm Projects/TestApp/testapp.py", line 32, in get
raise MyGenericException('A generic error', status_code=505)
MyGenericException
@app.errorhandler
装饰器似乎已为自定义 MyGenericException
异常正确设置。为什么 Flask 不处理它?
感谢任何能提供帮助的人。
关于两者 this question, and the docs,我从两者那里得到的关键信息是,如果您的路线是 Flask-RESTful 路线,那么您的路线将由 handle_error()
处理,防止或自定义此问题的唯一方法是实现您自己的 API class,并覆盖 handle_error()
.
根据@dylanj.nz 的回答 this vanilla-Flask error handling method, and this example of overriding Flask-RESTful's API ,这是我确定的方法。它允许 Flask-RESTful 处理 HTTPException
类型的异常,但将其他所有内容传递给默认的 (Flask) 处理程序,可以在其中指定自定义错误消息([= 的整个 JSON 对象15=] 个条目,如果需要的话)在异常发生时。
from flask_restful import Resource, Api as _Api, HTTPException
app = Flask(__name__)
# This new Exception will accept a message, a status code, and a
# payload of other values to be displayed as a JSON object
class FlaskGenericException(Exception):
status_code = 500 # default unless overridden
def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
@app.errorhandler(FlaskGenericException)
def handle_flask_generic_error(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response
# This overridden Flask-RESTful API class will keep Flask-RESTful
# from handling errors other than HTTPException ones.
class Api(_Api):
def error_router(self, original_handler, e):
# Override original error_router to only handle HTTPExceptions.
if self._has_fr_route() and isinstance(e, HTTPException):
try:
# Use Flask-RESTful's error handling method
return self.handle_error(e)
except Exception:
# Fall through to original handler (i.e. Flask)
pass
return original_handler(e)
api = Api(app)
class TestMe(Resource):
def get(self):
try:
ldapc = ldap.connection
except:
# message = first parameter. Other parameters come in as "payload"
raise FlaskGenericException('A generic error', status_code=505, payload={'user': 'John Doe', 'company': 'Foobar Corp.'})
api.add_resource(TestMe, '/testme', endpoint='TestMe')
我正在尝试在 Flask 1.0.2 和 Flask-RESTful 0.3.7 中创建自定义错误处理程序,使用“Implementing API Exceptions" page. (Flask-RESTful has its own way of creating custom error messages”中的指南,但因为它似乎为了有办法在异常发生时接受自定义的错误消息,我正在尝试改用 vanilla Flask 方法。)
from flask import Flask, jsonify
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
#########################################
class MyGenericException(Exception):
status_code = 500
def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
@app.errorhandler(MyGenericException)
def handle_generic_error(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response
#########################################
class TestMe(Resource):
def get(self):
raise MyGenericException('A generic error', status_code=501)
api.add_resource(TestMe, '/testme', endpoint='TestMe')
#########################################
if __name__ == '__main__':
app.run(debug=False)
仅调用 http://127.0.0.1:5000/testme returns 一条通用的“500 内部服务器错误”消息,而不是带有我的自定义错误文本的 501 错误。似乎 MyGenericException
被正确提升,但 Flask 似乎忽略了它。
[2019-05-08 17:09:18,409] ERROR in app: Exception on /testme [GET]
Traceback (most recent call last):
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask_restful\__init__.py", line 458, in wrapper
resp = resource(*args, **kwargs)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask\views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "C:\Users\testuser\Envs\testenv\lib\site-packages\flask_restful\__init__.py", line 573, in dispatch_request
resp = meth(*args, **kwargs)
File "C:/Users/testuser/Documents/PyCharm Projects/TestApp/testapp.py", line 32, in get
raise MyGenericException('A generic error', status_code=505)
MyGenericException
@app.errorhandler
装饰器似乎已为自定义 MyGenericException
异常正确设置。为什么 Flask 不处理它?
感谢任何能提供帮助的人。
关于两者 this question, and the docs,我从两者那里得到的关键信息是,如果您的路线是 Flask-RESTful 路线,那么您的路线将由 handle_error()
处理,防止或自定义此问题的唯一方法是实现您自己的 API class,并覆盖 handle_error()
.
根据@dylanj.nz 的回答 this vanilla-Flask error handling method, and this example of overriding Flask-RESTful's API ,这是我确定的方法。它允许 Flask-RESTful 处理 HTTPException
类型的异常,但将其他所有内容传递给默认的 (Flask) 处理程序,可以在其中指定自定义错误消息([= 的整个 JSON 对象15=] 个条目,如果需要的话)在异常发生时。
from flask_restful import Resource, Api as _Api, HTTPException
app = Flask(__name__)
# This new Exception will accept a message, a status code, and a
# payload of other values to be displayed as a JSON object
class FlaskGenericException(Exception):
status_code = 500 # default unless overridden
def __init__(self, message, status_code=None, payload=None):
Exception.__init__(self)
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
@app.errorhandler(FlaskGenericException)
def handle_flask_generic_error(error):
response = jsonify(error.to_dict())
response.status_code = error.status_code
return response
# This overridden Flask-RESTful API class will keep Flask-RESTful
# from handling errors other than HTTPException ones.
class Api(_Api):
def error_router(self, original_handler, e):
# Override original error_router to only handle HTTPExceptions.
if self._has_fr_route() and isinstance(e, HTTPException):
try:
# Use Flask-RESTful's error handling method
return self.handle_error(e)
except Exception:
# Fall through to original handler (i.e. Flask)
pass
return original_handler(e)
api = Api(app)
class TestMe(Resource):
def get(self):
try:
ldapc = ldap.connection
except:
# message = first parameter. Other parameters come in as "payload"
raise FlaskGenericException('A generic error', status_code=505, payload={'user': 'John Doe', 'company': 'Foobar Corp.'})
api.add_resource(TestMe, '/testme', endpoint='TestMe')