【问题标题】:Catching Exceptions on Python Flask RestPlus在 Python Flask RestPlus 上捕获异常
【发布时间】:2018-06-17 22:10:11
【问题描述】:

当对我的一个 API 的调用未返回任何结果时,我正在努力寻找一种返回响应的方法。我正在使用flask_restplus,并尝试使用@api.errorhandler 注释但没有成功,然后我在课堂上尝试了一个普通的try/except 块。

在这个特定问题中,我试图调用端点,其中 GUID 是数据库中不存在的用户。

http://localhost:5000/api/users/b3d8e86b-f2ad-4b6a-b768-e7adc1d94ced

用户端点定义如下:

import logging

from flask import Response
from flask_restplus import Resource, fields
from neomodel.core import DoesNotExist

from app.api.restplus import api
from app.models import User

log = logging.getLogger(__name__)

ns = api.namespace('users', description='Users')

user = api.model('user', {
    'id': fields.Integer(readOnly=True, description='The internal id of of a user'),
    'user_id': fields.String(required=True, description='The user unique identifier')}
)

@ns.route('/')
@api.response(404, 'Users not found.')
class UsersList(Resource):

    @api.marshal_list_with(user)
    def get(self):
        """
        Returns a list of all users
        :return: list_of_users
        """
        try:
            users = User.nodes
            list_of_users = list(users)
            return list_of_users
    #        return json.dumps(dict(users = [user.serialize for user in list_of_users]))
        except DoesNotExist:
            return Response(('{"No Content": "No user nodes found"}'), status = 200, mimetype = 'application/json')


@ns.route('/<string:user_id>')
class UserItem(Resource):

   @api.marshal_with(user)
   def get(self, user_id):
        """
        Returns a user with the given user_id
        :param id: user_id
        :return: user
        """
        try:
            user = User.nodes.get(user_id=user_id)
            return user
        except User.DoesNotExist:
            return Response({'message': 'Could not locate a user with the user_id provided.'}, 404)

我的初始化是在 app/init.py 中完成的:

import logging.config
from flask import Flask, Blueprint
from neomodel import clear_neo4j_database
from neomodel import db

from app.config import Configuration
from app.web_app.routes import webapp_mod
from app.data_loader.routes import dataloader_mod
from app.utilities import prepare_rerun
from app.api.endpoints.users import ns as users_namespace
from app.api.endpoints.sessions import ns as sessions_namespace
from app.api.endpoints.browsers import ns as browsers_namespace
from app.api.endpoints.os import ns as os_namespace
from app.api.endpoints.applications import ns as applications_namespace
from app.api.endpoints.tenants import ns as tenants_namepspace
from app.api.endpoints.devices import  ns as devices_namespace
from app.api.endpoints.environments import ns as environments_namespace

from app.api.restplus import api
from os import path


app = Flask(__name__)
app.config.from_object(Configuration)
app.register_blueprint(dataloader_mod, url_prefix='/data_loader')
log_file_path = path.join(path.dirname(path.abspath(__file__)), 'logging.conf')
logging.config.fileConfig(log_file_path)
log = logging.getLogger(__name__)

blueprint = Blueprint('api', __name__, url_prefix='/api')
api.init_app(blueprint)
api.add_namespace(users_namespace)
api.add_namespace(sessions_namespace)
api.add_namespace(browsers_namespace)
api.add_namespace(applications_namespace)
api.add_namespace(tenants_namepspace)
api.add_namespace(devices_namespace)
api.add_namespace(os_namespace)
api.add_namespace(environments_namespace)

我此时定义api的resplus.py模块只有api对象的定义,但是我尝试过网上的一些例子,并在其中定义了通过users对象中的注释处理异常的方法.

from flask_restplus import Api
from neomodel.core import DoesNotExist

api = Api(version='1.0', title='Users Activity Log',
          description='An API to retreive information about users'' activities in Infor Ming.le')

但是,当我拨打电话时,我收到的不是带有消息和 404 代码的 JSON 响应,而是:

{
    "id": null,
    "user_id": null
}

提前感谢您的帮助。

【问题讨论】:

  • 我遇到了同样的错误。您已经找到解决方案了吗?

标签: python flask flask-restful flask-restplus


【解决方案1】:

我想我帮助有点晚了,但我可能会帮助其他有同样问题的人:

问题是,尽管您有其他返回码(并且您有错误),但烧瓶仍然尝试使用 @marshal_with(user)。一开始可能有点混乱。

如果您查看此answer,您可以看到如何在不失去招摇功能的情况下返回多种答案类型,而且您仍然可以进行编组。这比标准的@marshal_with 更通用一点。

还有其他方法可以实现类似的错误结果:例如您可以使用 abort() 函数(在某些情况下可能更合乎逻辑)。

换句话说,您转换后的代码看起来像这样:

import logging

from flask import Response
from flask_restplus import Resource, fields, marshal
from neomodel.core import DoesNotExist

from app.api.restplus import api
from app.models import User

log = logging.getLogger(__name__)

ns = api.namespace('users', description='Users')

user = api.model('user', {
    'id': fields.Integer(readOnly=True, description='The internal id of of a user'),
    'user_id': fields.String(required=True, description='The user unique identifier')}
)

@ns.route('/')
@api.response(404, 'Users not found.')
class UsersList(Resource):

    @api.response(model=user, code=200)
    @api.response(404, 'Users not found.')
    def get(self):
        """
        Returns a list of all users
        :return: list_of_users
        """
        try:
            users = User.nodes
            list_of_users = list(users)
            return marshal(list_of_users)
        except DoesNotExist:
            return {"No Content": "No user nodes found"}, 404


@ns.route('/<string:user_id>')
class UserItem(Resource):

   @api.response(model=user, code=200)
   @api.response(code=404, 'Users not found.')
   def get(self, user_id):
        """
        Returns a user with the given user_id
        :param id: user_id
        :return: user
        """
        try:
            user = User.nodes.get(user_id=user_id)
            return marshal(user)
        except User.DoesNotExist:
            return {'message': 'Could not locate a user with the user_id provided.'}, 404

# More Endpoints - I hope this did the job...

【讨论】:

    【解决方案2】:

    你可以使用

    from flask_restplus import abort
    abort(400, custom='value')
    

    中止并通过错误

    namespace.abort(400, "An error occured") 
    

    【讨论】:

      【解决方案3】:

      这可能不再相关,因为您的问题来自很久以前,但我在四处寻找flask-restplus 异常处理最佳实践时遇到了这个问题。我认为您的问题不在于 flask-restplus 的异常处理。当用户不存在时,听起来您的 User 类没有引发 DoesNotExist 异常。您是否验证过您是否甚至点击了 except: 块?

      无论如何,一旦您确认您确实引发了 DoesNotExist 异常,您可以在 init.py 中为该异常注册一个错误处理程序,如下所示:

      @api.errorhandler(DoesNotExist)
      def handle_user_does_not_exist_error(error):
          return ({'message': 'Could not locate a user with the user_id provided.'}, 404) 
      

      【讨论】:

      • 这个问题依然存在。
      猜你喜欢
      • 2020-09-04
      • 2019-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      相关资源
      最近更新 更多