处理Flask路线中的所有异常

时间:2018-12-10 09:25:05

标签: python flask python-decorators endpoint

我的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)

但是,装饰器似乎没有作用。

3 个答案:

答案 0 :(得分:0)

这就是您需要的:

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)

答案 1 :(得分:0)

正如@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。

答案 2 :(得分:0)

我强烈建议使用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'...