Flask restAPI 中的错误处理最佳实践是什么

时间:2021-05-03 07:15:33

标签: python rest flask

烧瓶==1.1.2 Python==3.8

我正在构建一个为机器学习模型提供服务的 restAPI。我的同事将向我的 restAPI 发送请求并使用结果将其发送给用户,他希望我向他发送适当的错误消息以及 status_code。

我对如何正确处理 Python Flask 中的错误进行了大量搜索,但我仍然坚持认为可扩展和可维护的 restAPI 的最佳实践是什么。

目前每当发生错误时,我都会返回带有消息和状态代码的字典。我想缓解这种方法的一些问题:

  1. 如果函数内部发生错误,它必须将包含错误消息的字典返回到调用函数的位置,并需要检查它是否确实是一个错误,如果是,则返回错误消息

    示例:

     def add_data(x,y):
         """return addition of x,y. They both need to be integers"""
         if type(x) != int:
             return "x has wrong datatype"
         if type(y) != int:
             return "y has wrong datatype"
         return x+y
    
     @app.route("/predict", methods=["POST"])
     def predict():
         data = request.get_json()
         result = add_data(data["x"], data["y"])
         if type(result) == str:
             return {"message":"input error", "status":222}
    
  2. 不能在函数内部破坏代码。

    遵循一些参考

    我已将代码更改为以下内容:

     class InputError(Exception):
         status_code = 400
         def __init__(self, message, status_code=None):
             Exception.__init__(self)
             self.message = message
             if status_code is not None:
                 self.status_code = status_code
    
         def __str__(self):
             return repr(self.status_code)
    
    
     def add_data(x,y):
         if type(x) != int:
             raise InputError("x has wrong datatype", status_code=222)
         if type(y) != int:
             raise InputError("y has wrong datatype", status_code=222)
         return x+y
    

    这确实破坏了发现错误的代码,但是我无法像以前一样找出如何返回字典。

我该怎么做?哪种做法被认为是最佳做法?

1 个答案:

答案 0 :(得分:1)

解决方案是使用错误处理程序 https://flask.palletsprojects.com/en/1.1.x/errorhandling/

就你而言:

@app.errorhandler(InputError)
def handle_input_error(e):
    return {"message": e["message"], "status": e["status"]}

现在每当你在代码中的某处引发 InputError 时,flask 就会知道调用这个方法并返回这个响应

如果您有更多类型的错误,我会切换到更一般的内容

class MyErrors(Exception):
    status_code: int
    
    def __init__(self, message):
        super(MyErrors, self).__init__(message)
        self.message = message
        
    def response(self):
        return {"message": self.message, "status": self.status_code}
    
class InputError(MyErrors):
    status_code = 222
    
class SomeOtherError(MyErrors):
    status_code = 123

@app.errorhandler(MyErrors)
def handle_errors(e):
    return e.response()