首页 > 解决方案 > 为什么在使用 Response 实例调用 abort 时不调用 HTTPException 的处理程序?

问题描述

from flask import Flask, abort, Response

from werkzeug.exceptions import HTTPException

app = Flask(__name__)


@app.errorhandler(HTTPException)
def http_exception_handler(e: HTTPException):
    msg = 'http_exception_handler is called.'
    print(msg)
    return msg


@app.route('/')
def index():
    try:
        abort(Response('I am the response passed to abort.', 400))
    except Exception as e:
        print(f'Raised error is an instance of HTTPException: {isinstance(e, HTTPException)}')
        raise e

    return 'Index successfully produced a response.'

在上面的代码中,为什么使用对象调用函数HTTPException时注册的处理程序没有被调用?代码的执行表明引发的错误是.abortResponseabortHTTPException

标签: flask

解决方案


TL;DR:不要传递 Response 对象。如果要使用 ErrorHandler,请使用 HTTP 代码。

所以,它看起来更复杂。您可以深入研究 Werkzeug 代码和 Flask 以查看发生了什么。我不打算详细说明步骤。

因此,在 Aborter 类上调用 abort()。这将从您的 Response 对象创建一个 HTTPException。

如果您运行以下命令,您将拥有:

>>> print(HTTPException(response=Response("BODY",404)))
??? Unknown Error: None

此 HTTPException 没有代码。

>>> print(HTTPException(response=Response("BODY", 404)).code)
None

这个由错误处理程序解释。

def handle_http_exception(self, e):
    if e.code is None:
        return e # Here's your return

    # This is never called.
    handler = self._find_error_handler(e)
    if handler is None:
        return e
    return handler(e)

然后你的处理程序装饰器将永远不会被调用。

所以这是详细步骤的一部分。但是因为 Flask 和 Werkzeug 的编码很好。您可以在此处直接阅读 HTTPException 类:

def get_response(self, environ=None):
    """Get a response object.  If one was passed to the exception
    it's returned directly.

就是这个意思,直接返回。这是有道理的。如果您已经管理了错误,为什么还要继续使用错误处理程序。

如果你想更深入地了解代码,这里有一些 github 链接:

Werkzeug Exception Flask App 类


推荐阅读