如何在使用自定义错误处理程序时访问abort命令的错误消息

63

使用Python Flask服务器,我希望能够通过abort命令抛出HTTP错误响应,并在响应体中使用自定义的响应字符串和消息。

@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.message})
    response.status_code = 404
    response.status = 'error.Bad Request'
    return response

abort(400,'{"message":"custom error message to appear in body"}')

但是error.message变量显示为空字符串。我似乎找不到关于如何通过自定义错误处理程序访问abort函数的第二个变量的文档。


3
“error.description”是你要找的吗? - dirn
4个回答

100
如果你查看 flask/__init__.py,你会发现 abort 实际上是从 werkzeug.exceptions 导入的。观察 Aborter,我们可以看到当使用数字代码调用时,会查找特定的 HTTPException 子类,并使用提供给 Aborter 实例的所有参数来调用它。观察 HTTPException,特别关注 第 85-89 行,我们可以看到传递给 HTTPException.__init__ 的第二个参数存储在 description 属性中,正如 @dirn 指出的那样。
你可以从 description 属性中获取消息:
@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.description['message']})
    # etc.

abort(400, {'message': 'custom error message to appear in body'})

或者仅传递描述本身:

@app.errorhandler(400)
def custom400(error):
    response = jsonify({'message': error.description})
    # etc.

abort(400, 'custom error message to appear in body')

2
这是一个非常好的方法,可以使用自定义错误消息扩展abort的功能。谢谢。 - pbojinov
2
有没有一种方法可以针对每个状态码进行操作,而不必为每个代码编写自定义错误处理程序?例如:abort(409, '存在时间冲突')abort(400, '自定义错误消息在正文中显示') - Alex Cory
重复答案 - https://dev59.com/HVcO5IYBdhLWcg3wrTgs#45412576 - debovis

75

人们过于依赖abort()。事实上,有更好的方法来处理错误。

例如,您可以编写这个辅助函数:

def bad_request(message):
    response = jsonify({'message': message})
    response.status_code = 400
    return response

然后从您的视图函数中,您可以使用以下代码返回错误:

@app.route('/')
def index():
    if error_condition:
        return bad_request('message that appears in body')

如果错误发生在调用堆栈的更深处,而且没有可能返回响应,那么您可以使用自定义异常。例如:

class BadRequestError(ValueError):
    pass

@app.errorhandler(BadRequestError)
def bad_request_handler(error):
    return bad_request(str(error))

然后在需要发出错误的函数中,你只需引发异常即可:

def some_function():
    if error_condition:
        raise BadRequestError('message that appears in the body')

我希望这可以帮到你。


1
当你可以直接使用return bad_request(...)而不是仅仅使用raise BadRequestError(...)时,是否更好(更快)? - Ciprian Tomoiagă
你可以在任何时候引发中止,无需返回。 - Minh Hoàng
这有什么改进之处吗?如果不是从视图中完成(并且您需要注册错误处理程序),唯一的区别是您调用raise BadRequestError而不是abort,还需要注册自定义异常,增加了复杂性。 - nirvana-msu

42

我只是这样做:

    abort(400, description="Required parameter is missing")

在我看来,这是最好的答案。 - Z.Wei
当您想返回一个JSON类型的响应时,您需要使用make_response函数。 - Minh Hoàng
1
为了澄清Minh在7月7日的评论,在Werkzeug>=1.0.1中,这个答案中的代码将生成一个正确的JSON响应。我甚至能够传递一个dict作为描述,Werkzeug会正确地生成一个嵌套的JSON响应。 - Peter Ilfrich
1
很不幸,这会返回HTML,我不想要它。我只想打印出信息。以下是curl输出的样子:`<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"><title>403 Forbidden</title> <h1>Forbidden</h1> <p>Required parameter is missing</p>` - Dave

10

flask.abort 还可以接受 flask.Response

abort(make_response(jsonify(message="Error message"), 400))

1
您甚至不需要使用jsonify:abort(make_response({'message': '错误消息'}, 400)) - Minh Hoàng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接