为什么未调用我的Flask错误处理程序?

时间:2019-05-08 21:47:05

标签: python exception flask error-handling flask-restful

我正在尝试使用“ Implementing API Exceptions”页面上的指南在Flask 1.0.2和Flask-RESTful 0.3.7中创建自定义错误处理程序。 (Flask-RESTful具有自己的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仅返回一般的“ 500 Internal Server Error”消息,但是不会返回带有我的自定义错误文本的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不处理它?

感谢任何可以提供帮助的人。

2 个答案:

答案 0 :(得分:1)

紧跟@ dylanj.nz的答案this vanilla-Flask error handling methodthis example of overriding Flask-RESTful's API,这是我所采用的方法。它允许Flask-RESTful处理HTTPException类型的异常,但是将其他所有内容传递给默认的(Flask)处理程序,在该处理程序中可以指定自定义错误消息(如果需要,可以包含键/值条目的整个JSON对象) )。

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')

答案 1 :(得分:0)

同时参考this questiondocs,我从这两者中获取的关键信息是,如果您的路线是Flask-RESTful,而您的路线是,则将由{ {1}},防止或自定义此错误的唯一方法是实现自己的API类,并覆盖handle_error()