###### tags: `Flask` # Python Flask API 例外處理 * 概念: * 在API的function前方加上@exception_handler裝飾器,功能邏輯需要return錯誤的時候,就直接raise自定義的exception。 * 所有例外要回傳的訊息統一用exception_hadler管理。 * 另外可以在自定義例外類別,客製化例外訊息、http status、error code。 ## API ```python=3 from utils.exception_handler import exception_handler @app.route('/user', methods=['POST']) @exception_handler def user_create(): api_key = request.headers.get('api-key') if api_key != customer_api_key: raise ApiHeaderAuthError() # raise ApiHeaderAuthError(message="other info", info="other info", code="error-001", status=501) data = request.json identity = data['identity'] friendly_name = data['friendly_name'] client.conversations.services(service_id).users.create(identity=identity, friendly_name=friendly_name, attributes=data) return jsonify({"message": "user created successfully"}) ``` ## utils.exception_handler ```python= import sys import traceback from functools import wraps from flask import jsonify from twilio.base.exceptions import TwilioRestException from utils.exceptions import * """ 抓取父類的例外,可以連同繼承此父類的例外都擷取到。 """ def exception_handler(func): @wraps(func) def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except TwilioRestException as e: return jsonify({"info": str(e.msg)}), e.status except ApiError as e: # print(e.__class__.__name__) # 可以查看例外子類class名稱 return {"code": e.code, "message": e.message, "info": e.info}, e.status except KeyError as e: return {"message": "key error", "info": str(e)}, 400 except Exception as e: traceback.print_tb(sys.exc_info()[2]) return {"message": "Something wrong", "info": str(e)}, 500 return wrapper ``` ## utils.exceptions ```python= class ApiError(Exception): """ A generic 400 or 500 level exception from the Twilio API :param str|None message: A human-readable brief message for the error :param str|None info: Detail information about the error :param str|None code: A self-defined error code for the error :param int|500 status: the HTTP status that was returned for the exception """ def __init__(self, message=None, info=None, code=None, status=500): self.message = message self.info = info self.code = code self.status = status def __str__(self): return self.message class ApiHeaderAuthError(ApiError): def __init__(self, message="Header auth failed.", info=None, code=None, status=401): super().__init__(message, info, code, status) ``` ###### tag: `Flask` `exception`