捕获 Flask API 中引发的自定义异常。引发的所有异常最终都会出现 500 错误 [重复]

2024-04-12

我希望能够在 API 中引发验证和其他异常,并在包装​​视图中捕获它们,该视图将以 JSON 形式返回错误消息。

我想我可以使用这样的东西:

例外

class APIException(Exception):

    def __init__(self, message, status_code=406):
        super().__init__(message)
        self.status_code = status_code

捕获异常

# Todo: find a better way of handling this. Flask should have some way of handling exceptions better than this
def catch_errors(view):
    @functools.wraps(view)
    def wrapped_view(**kwargs):
        try:
            return view(**kwargs)
        except APIException as e:
            # It seems to hit here
            return json_response({'message': str(e)}, e.status_code) 
        except Exception as e:
            # But bubbles up to here and returns this
            return json_response({'message': str(e)}, 500)

    return wrapped_view

Route

@router.route('/a-route', methods=['POST'])
@catch_errors
def get():
    return json_response(ARouteAPI().post(request.get_json()))

API处理后

class ARouteAPI():

    def post(data):
        if not data.something:
            raise APIException("Invalid data error")

我遇到的问题是,无论我抛出什么异常,它都会冒泡到一个完整的异常Exception并击中500所以它永远不会返回APIException.

有谁知道为什么?如何修复它?

或者有更好的方法来处理这个问题吗?

Update

至今仍为此做噩梦。

处理它的更好方法是使用@app.errorhandler装饰器(在我的例子中@router是我的蓝图名称,所以我正在使用@router.errorhandler相反),正如@Hyunwoo 所建议的。

然而,无论抛出什么异常,它总是会遇到 500 错误,我不知道为什么。

我发现了类似的例子,其中调试模式导致问题重新出现,我认为这可能会导致问题,但我将调试模式设置为false

错误处理程序

router = Blueprint('router', __name__)


@router.errorhandler(APIException)
def api_exception_handler(e):
    return jsonify({'message': str(e)}, e.status_code), 400

@router.errorhandler(500)
def error_handler(e):
    return jsonify({'message': str(e)}), 500 # Always hits this whatever exception is raised

堆栈跟踪

[2018-10-16 23:48:39,767] ERROR in app: Exception on /drone/7 [PUT]
Traceback (most recent call last):
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/sarcoma/PycharmProjects/drone_squadron/venv/lib/python3.5/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/sarcoma/PycharmProjects/drone_squadron/drone_squadron/router.py", line 62, in wrapped_view
    return view(**kwargs)
  File "/home/sarcoma/PycharmProjects/drone_squadron/drone_squadron/router.py", line 159, in drone_detail
    return JsonRequestHandler.detail(DroneApi(), item_id)
  File "/home/sarcoma/PycharmProjects/drone_squadron/drone_squadron/request/json_request_handler.py", line 39, in detail
    return json_response(api.put(item_id, request.get_json()))
  File "/home/sarcoma/PycharmProjects/drone_squadron/drone_squadron/api/drone_api.py", line 42, in put
    raise APIException("Not enough scrap")
drone_squadron.exception.exceptions.APIException: Not enough scrap
127.0.0.1 - - [16/Oct/2018 23:48:39] "PUT /drone/7 HTTP/1.1" 500 -

错误处理规范

这是输出print(app.error_handler_spec)正如@Hyunwoo 所建议的。

{None: {
    500: {<class 'werkzeug.exceptions.InternalServerError'>: <function error_handler at 0x7fdd0cb6ad08>}, 
    None: {
        <class 'sqlalchemy.exc.IntegrityError'>: <function integrity_error_handler at 0x7fdd0cb6ab70>, 
        <class 'exception.exceptions.APIException'>: <function api_exception_handler at 0x7fdd0cb6abf8>, 
        <class 'exception.exceptions.ValidationException'>: <function validation_exception_handler at 0x7fdd0cb6ac80>
}}}

I used app.errorhandler用于处理烧瓶中的错误。 (无论是自定义错误,还是标准错误)

# IntegrityError Error handler
@app.errorhandler(IntegrityError)
def exception_handler(e):
    return jsonify({'message': e._message().split('"')[2].strip()}), 400


# Custom Error handler

# Duplicated column value
@app.errorhandler(APIException)
def exception_handler(e):
    return jsonify({'message': e.description}), 400

和视图中的用法相同

@app.route('/')
def index():
    if something_wrong():
        raise APIException

class ARouteAPI():
    def post(data):
        if not data.something:
            raise APIException("Invalid data error")

不要忘记确保您的处理程序是由 Flask 应用程序添加的

>>> print(app.error_handler_spec)
{None: {None: {<class 'sqlalchemy.exc.IntegrityError'>: <function exception_handler at 0x10ae24158>,
               <class 'app.error.exc.DuplicatedValueError'>: <function exception_handler at 0x10ae54268>,
               <class 'app.error.exc.WrongSelectionError'>: <function exception_handler at 0x10ae542f0>},
        404: {<class 'werkzeug.exceptions.NotFound'>: <function exception_handler at 0x10a53c7b8>}}}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

捕获 Flask API 中引发的自定义异常。引发的所有异常最终都会出现 500 错误 [重复] 的相关文章

随机推荐

  • Xamarin:使用布局的启动屏幕

    我正在尝试为我的 Android 应用程序创建启动屏幕 如此链接所示http developer xamarin com guides android user interface creating a splash screen http
  • 如何在 JLayeredPane 上设置背景颜色?

    我很好奇为什么在 JLayeredPane 上调用 setBackground Color 似乎并没有真正设置背景颜色 我猜这与 JLayeredPane 由于某种原因必须具有透明背景有关 不管怎样 这里有一些代码显示了这个问题 这是在 M
  • ajax请求后如何更改URL?

    我有一个菜单 其中包含一些更新 div 的链接content并执行该函数onSuccess加载后 li Ajax ActionLink Home Index home li li Ajax ActionLink Download Index
  • 通过编辑 AOSP 将 Android 导航栏放在侧面

    我想通过编辑 AOSP 将导航栏 具有后退 主页和菜单等系统软键 而不是导航抽屉 放在 右侧 侧 如下所示 Status bar always N Layout with background drawable a v Title Acti
  • Java - 替换 JFrame 中的组件

    我正在努力使用 java GUI 提前感谢您的帮助 我有一个 JFrame 其中有几个组件 按钮 J 按钮 触发动作侦听器 comp这是我试图替换的一个组件JScrollPane其中有一个组件 组件的类型无关紧要 可以是文本字段 表格或任何
  • android - TextView 中自动滚动的问题

    我有一个Activity它用作音乐播放器 当它开始时 一个MediaPlayer对象被初始化并启动 在布局中 我有TextViews显示艺术家和标题 这些值 从服务器检索 可能很长 所以我添加了 android ellipsize marq
  • ruby 中的网络掩码到 CIDR

    我一直在使用 ip address gem 它似乎无法从以下形式的网络掩码进行转换 255 255 255 0 进入 CIDR 表格 24 有谁知道如何快速将前者转换为后者 这是快速而肮脏的方法 require ipaddr puts IP
  • 使用 ramdajs 重命名对象的属性

    我需要使用以下命令将可能包含连字符的单词重写为驼峰命名法的对象的所有属性ramdajs 示例 属性名称animation timing function应该成为animationTimingFunction每个键依此类推 您能否举个例子 这
  • 为什么缩放填充会给出比 UIImageVIew 尺寸更大的图像? (使用快速)

    我正在尝试显示地名列表 包括它的照片PFQueryTableViewController 它包含在 ParseUI SDK 中解析网 http parse com 我已经成功地展示了图像 不幸的是 当我将 UIImageView 模式更改为
  • 需要帮助在 javascript 中的表之间切换

    我试图使用两个按钮来使用 javascript 在两个表之间切换 但是每当我测试时 两个表都会出现 而不是只出现一个 var table1 document getElementById table1 var table2 document
  • 最小可行的网站图标代码

    我很困惑什么是让网站图标在大多数手机和浏览器上工作的最简单方法 1 一些网站 https mathiasbynens be notes touch icons建议使用以下内容就足够了 这适用于 iOS 8 并且应该适用于 Android B
  • UI线程块

    我创建了一个简单的 WPF 应用程序 并向默认窗口添加了一个按钮 当我单击按钮时 会调用一个模拟的长工作方法 使用 Thread Sleep 15000 进行模拟 我试图使按钮异步执行 但是尽管遵循在线示例 按钮和整个窗口都会在我锁定时立即
  • “循环”引用是否会被视为 WeakMap 的“可达性”?

    function f const w new WeakMap const o w set o v o return w const weakMap f 对于给定的代码 唯一的weakMap项目是否被视为可达 那么 它会被垃圾收集吗 PS 这
  • 如何禁用 Google Fit 并撤销应用程序本身的权限

    我已经设置了连接到 Google Fit 的应用程序 读取和写入一些有关用户身体的数据 当用户在应用程序设置中禁用 Google Fit 时 我尝试通过调用以下命令来撤销我的应用程序权限 public void disableGoogleF
  • 当数据在缓存中时 Apollo Client client.readQuery 返回 null

    这一定是用户错误 但我有一个简单的应用程序currentUser查询在 JWT 中查找 id 查找它并返回相应的用户 我可以查看 devtools 并看到它在缓存中 ref User 19 export const CURRENT USER
  • 要在 Google App Engine 上托管静态 (HTML) 网站,app.yaml 文件中应包含哪些内容?

    我可以用它来上传 HTML 页面吗 app yaml内容 application visualvidya version 1 runtime python api version 1 handlers url gif png jpg ico
  • 我应该在 HTML 中使用 % 或 'px'

    无论是 HTML XHTML 还是 HTML5 您都会发现到处都是令人讨厌的百分比 然而 我看到很多网站都不敢靠近它们 然而大学总是鼓励我使用它们 那么我应该使用哪个 哪一个会带来更好的网站设计 为什么 我知道要避免使用高度 尽管如果我想使
  • 使用锚点提交表单安全吗?

    我在某处读到 使用锚标记提交表单不太安全 所以这就是我的问题 使用锚标记而不是安全吗
  • Curl 同时下载和上传同一文件

    不确定是否可能 但我一直在尝试使用curl 从 HTTP 位置下载文件并将其输出到 FTP 服务器上 如果这实际上可能的话 我真的很希望得到一些帮助 curl http example com down curl T ftp mysite
  • 捕获 Flask API 中引发的自定义异常。引发的所有异常最终都会出现 500 错误 [重复]

    这个问题在这里已经有答案了 我希望能够在 API 中引发验证和其他异常 并在包装 视图中捕获它们 该视图将以 JSON 形式返回错误消息 我想我可以使用这样的东西 例外 class APIException Exception def in