【问题标题】:Handle all exceptions in Flask route处理 Flask 路由中的所有异常
【发布时间】:2019-05-11 04:14:46
【问题描述】:

我的 Flask 应用中有一条简单的路线:

@app.route('/', methods=['GET'])
def homepage():
    return '{}'.format(1 / 0)

当用户访问 site.com/ 时,她应该会看到 1/0 的结果。当然这是不可能的,所以 Python 会抛出一个错误。

现在,我希望以特殊方式处理所有端点上的所有错误:我希望它们返回 JSON 响应,例如:

{
    'status_code': 500,
    'status': 'Internal Server Error'
}

我写了一个装饰器来做这个:

def return_500_if_errors(f):
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except:
            response = {
                'status_code': 500,
                'status': 'Internal Server Error'
            }
            return flask.jsonify(response), 500
    return wrapper

然后我将装饰器添加到端点:

@return_500_if_errors
@app.route('/', methods=['GET'])
def homepage():
    return '{}'.format.(1 / 0)

但是,装饰器似乎没有效果。

【问题讨论】:

  • 装饰器的顺序很重要
  • @YiFei 我试图颠倒顺序,同样的结果。
  • 关心发布反码?我刚试过自己,你的装饰器没有问题。请注意 Joost 如何使用装饰器。 @app.route 必须是最外面的。
  • @YiFei 我感觉很糟糕,因为我确定我尝试过更改装饰器的顺序。然而,我今天又试了一次,你确实是对的——它有效。很抱歉提供误导性信息!
  • 为什么不使用flask的错误处理器?

标签: python flask python-decorators endpoint


【解决方案1】:

这是你需要的:

from flask import Flask, jsonify
from functools import wraps

app = Flask(__name__)

def catch_custom_exception(func):
    @wraps(func)
    def decorated_function(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            return str(e), 500
    return decorated_function

@app.route('/', methods=['GET'])
@catch_custom_exception
def homepage():
    return '{}'.format(1 / 0)

@app.route('/2', methods=['GET'])
def homepage2():
    return '{}'.format(1 / 0)

【讨论】:

  • 感谢您的回复。这可能有效,但我不太喜欢这种方法。例如,如果我想省略一些端点怎么办?另外,你知道为什么装饰器方法不起作用吗?
【解决方案2】:

正如@YiFei 和@Joost 所指出的,问题在于装饰器的顺序。

这确实有效:

def return_500_if_errors(f):
    def wrapper(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except:
            response = {
                'status_code': 500,
                'status': 'Internal Server Error'
            }
            return flask.jsonify(response), 500
    return wrapper

@app.route('/', methods=['GET'])
@return_500_if_errors
def homepage():
    return '{}'.format.(1 / 0)

@Joost 的回答类似,但在某种程度上有所不同,因为要捕获并返回错误本身 - 而不是标准化的 JSON。

【讨论】:

    【解决方案3】:

    我强烈建议使用 Flask 的 error handler 已经存在的装饰器。

    基本上应该是这样的:

    # flask will check if raised exception is of type 'SomeException' (or lower)
    # if so, will just execute this method
    @app.errorhandler(SomeException) 
    def handle_error(error):
        response = jsonify(error.to_dict())
        response.status_code = error.status_code
        return response
    
    # An exception will be raised, hopefully to be caught by 'handle_error'    
    @app.route('/', methods=['GET'])
    def homepage():
        return '{}'.format.(1 / 0)
    

    只要确保要捕获的异常将具有“status_code”或如果没有则输入“500”...

    【讨论】:

    • 这已经被讨论过了,它并没有完全满足我的需求。有关更多详细信息,请参阅@Joost 答案的编辑历史记录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    相关资源
    最近更新 更多