可序列化的python异常以烧瓶http响应。

Flask-ApiExceptions的Python项目详细描述


烧瓶APIexceptions是一个烧瓶扩展,它提供了 将未捕获异常序列化为http响应的功能 基于json的rest api。

安装

您可以使用pip

安装此扩展
$ pip install flask_apiexceptions

或者,您可以克隆存储库:

$ git clone https://github.com/jperras/flask_apiexceptions.git

运行测试

Tox用于运行测试, 是用PyTest写的。 要运行它们,请克隆存储库(如上所示),确保tox 已安装并可用,运行:

$ cd path/to/flask_apiexceptions
$ tox

用法

此包包含名为JSONExceptionHandler的扩展名,该扩展名 可按常规方式添加到应用程序中:

from flask import Flask
from flask_apiexceptions import JSONExceptionHandler

app = Flask(__name__)
exception_handler = JSONExceptionHandler(app)

如果 您正在使用应用程序工厂:

exception_handler = JSONExceptionHandler()
exception_hander.init_app(app)

一旦初始化,扩展实际上在默认情况下不会执行任何操作。 您必须将其配置为处理Werkzeug HTTP错误代码或 自定义Exception类。

自定义异常类处理

显示如何在视图中引发自定义异常的示例 方法,并将该异常转换为json响应:

classMissingUserError(Exception):status_code=404message='No such user exists.'@app.route('/not-found')deftesting():raiseMissingUserError()ext=JSONExceptionHandler(app)ext.register(code_or_exception=MissingUserError)withapp.app_context():withapp.test_client()asc:rv=c.get('/not-found')assertrv.status_code==404assertrv.headers['content-type']=='application/json'assertjson.loads(rv.data)['message']=='No such user exists.'

这使用JSONExceptionHandler.default_handler()来转换 将CustomError异常类转换为适当的响应。它 尝试内省为^{tt7}返回的异常实例$ 或者^ {t8}$$属性,还检查是否存在 status_code属性。

如果找到这些字段中的任何一个,则默认处理程序将填充 使用给定消息的响应数据,并设置响应状态代码。 如果不存在消息或状态代码,则默认响应为 {"message": "An error occurred!"}带有 HTTP/1.1 500 Internal Server Error状态代码已设置。

如果您想以不同的方式处理自定义异常类, 假设您在异常中捕获了更复杂的数据 实例,或属性不方便命名为messagedescription,然后可以为异常指定自定义处理程序 类型:

fromflask_apiexceptionsimportJSONExceptionHandlerapp=Flask(__name__)ext=JSONExceptionHandler(app)classCaffeineError(Exception):teapot_code=418special={'foo':'bar'}defcaffeine_handler(error):response=jsonify(data=error.special)response.status_code=error.teapot_codereturnresponse@app.route('/testing')deftesting():raiseCaffeineError()ext.register(code_or_exception=CaffeineError,handler=caffeine_handler)withapp.app_context():withapp.test_client()asc:rv=c.get('/testing')assertrv.status_code==418assertrv.headers['content-type']=='application/json'assertjson.loads(rv.data)['data']==CaffeineError.special

顺便说一下,这也是如何使用响应内容类型的 而不是application/json。简单地构建自己的响应 对象不允许在处理程序中使用jsonify(),只要它 作为返回值生成有效的响应。

使用ApiExceptionApiError对象

Flask-ApiExceptions包括一些便利类和一个处理程序 用于设置结构化API错误响应的方法。他们完全 可选,但提供一些正常的默认值 情况。

一个ApiException实例包装一个或多个ApiError实例。 从这个意义上讲,ApiException只是 实际错误消息。ApiError实例接受可选 codemessageinfo属性。

其思想是code应该是 错误,例如invalid-datadoes-not-exist。这个 message字段应该提供更详细和精确的描述 错误的。info字段可用于任何其他元数据 或可能需要的非结构化信息。

如果使用info字段,则该字段应包含json数据 可序列化。

要使用这些结构,需要注册适当的异常 类以及为 目的:

fromflask_apiexceptionsimport(JSONExceptionHandler,ApiException,ApiError,api_exception_handler)app=Flask(__name__)ext=JSONExceptionHandler(app)ext.register(code_or_exception=ApiException,handler=api_exception_handler)@app.route('/custom')deftesting():error=ApiError(code='teapot',message='I am a little teapot.')raiseApiException(status_code=418,error=error)withapp.app_context():withapp.test_client()asc:rv=c.get('/custom')# JSON response looks like...# {"errors": [{"code": "teapot", "message": "I am a little teapot."}]}assertrv.status_code==418assertrv.headers['content-type']=='application/json'json_data=json.loads(rv.data)assertjson_data['errors'][0]['message']=='I am a little teapot.'assertjson_data['errors'][0]['code']=='teapot'assertjson_data['errors'][0]['info']isNone

请注意,当使用ApiExceptionApiError类时, 在ApiException实例上设置了状态代码。这会使更多 当您可以将多个ApiError对象设置为同一对象时进行检测 ApiException

fromflask_apiexceptionsimportApiException,ApiError# ...@app.route('/testing')deftesting():exc=ApiException(status_code=400)invalid_address_error=ApiError(code='invalid-data',message='The address provided is invalid.')invalid_phone_error=ApiError(code='invalid-data',message='The phone number does not exist.',info={'area_code':'555'})exc.add_error(invalid_address_error)exc.add_error(invalid_phone_error)raiseexc# JSON response format:# {"errors": [#     {"code": "invalid-data", "message": "The address provided is invalid."},#     {"code": "invalid-data", "message": "The phone number does not exist.", "info": {"area_code": "444"}}# ]}

如果您只想在 ApiException,这可以通过后者的构造函数作为 速记:

exc=ApiException(status_code=400,code='invalid-data',message='The address provided is invalid',info={'zip_code':'90210'})

相当于:

exc=ApiException(status_code=400)error=ApiError(code='invalid-data',message='The address provided is invalid',info={'zip_code':'90210'}))exc.add_error(error)

一个有用的模式是将ApiException子类化为明显有用的 异常类型,在此类型上可以定义 将用于在instantial上填充正确的error对象打开。为了 示例:

classMissingResourceError(ApiException):status_code=404message="No such resource exists."code='not-found'# ...@app.route('/posts/<int:post_id>')defpost_by_id(post_id):"""Fetch a single post by ID from the database."""post=Post.query.filter(Post.id==post_id).one_or_none()ifpostisNone:raiseMissingResourceError()# 404 response, wiht JSON body:# {"errors": [#     {"code": "not-found", "message": "No such resource exists."}# ]}

这个特殊模式的好处是你可以 语义上更正代码库中的异常,并可以选择 在调用堆栈中处理它们。如果你不处理它们,它们就会冒出来 到异常处理程序(如果您配置了 flask_apiexceptions.api_exception_handler或类似)注册 烧瓶,然后转换为请求客户端的有用响应。

classMissingResourceError(ApiException):status_code=404message="No such resource exists."code='not-found'classPost(db.Model):# ...@classmethoddefquery_by_id(cls,post_id):"""Query Post by ID, raise exception if not found."""result=cls.query.filter(cls.id==post_id).one_or_none()ifresultisNone:raiseMissingResourceError()returnresult@app.route('/posts/<int:post_id>')defpost_by_id(post_id):"""Fetch a single post by ID from the database."""try:post=Post.query_by_id(post_id)exceptMissingResourceErrorase:# We can do whatever we want now that we've caught the exception.# For the sake of illustration, we're just going to log it.app.logger.exception("Could not locate post!")# Will bubble up the exception until it is rendered to JSON# for the client.raisee

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
具有MVC模式的java观察者/可观察对象   java junit在测试执行后未清理记录器   java减少spring boot应用程序中的网络延迟   java MyFirstApp教程Android Studio sendMessage问题   java无法转换消息   java JSP如果是,则递增   URL和方法的java spring安全设置   spring中的java自动动态绑定   java在Wicket中构建表   使用JUnit在与main相同的类中使用java测试方法   使用tomcat 8管理器部署后,java找不到WAR文件路径   java原子整数错误行为   需要java吗?   java允许多个JLabel中的文本重叠   java Hadoop mapreduce映射程序编程   json参数化Jackson Java库的JsonProperty值