【FastAPI后台API 六】统一响应异常处理

异常处理

统一捕获处理异常,使得代码更加完善,健壮。 框架内置了一些异常,当然也可以自己定义异常然后捕获处理。

完全可以参考官网(超喜欢这种风格的文档): https://fastapi.tiangolo.com/tutorial/handling-errors/

异常捕获

在FastAPI中,最常见的就是请求参数验证异常处理,因为FastAPI全面使用了pydantic来做数据类型校验,所以最常见的异常就是ValidationError , 然后FastAPI继承了这个错误,专门捕获请求参数异常的RequestValidationError

捕获异常的语法

from fastapi.exceptions import RequestValidationError

@app.exception_handler(RequestValidationError)
    async def request_validation_exception_handler(request: Request, exc: RequestValidationError):
        """
        请求参数验证异常
        :param request: 请求头信息
        :param exc: 异常对象
        :return:
        """
        # 日志记录异常详细上下文 
        logger.error(f"全局异\n{request.method}URL{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
        return response_code.resp_422(message=exc.errors())

自定义异常

我是这样做的,在utils/custom_exc.py文件下定义好各种异常

class UserTokenError(Exception):
    def __init__(self, err_desc: str = "用户认证异常"):
        self.err_desc = err_desc


class UserNotFound(Exception):
    def __init__(self, err_desc: str = "没有此用户"):
        self.err_desc = err_desc

抛出自定异常

先倒入异常,然后raise抛出

from utils import custom_exc
# xxxx
raise custom_exc.UserTokenError(err_desc="access token fail")

捕获自定异常

这个和内置异常捕获语法是一样的

@app.exception_handler(UserTokenError)
async def user_token_exception_handler(request: Request, exc: UserTokenError):
    """
    用户token异常
    :param request:
    :param exc:
    :return:
    """
    logger.error(f"用户认证异常\nURL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")

    return response_code.resp_5000(message=exc.err_desc)

注册异常

一般项目中会捕获各种异常, 最好就是把异常函数集中起来,我是模仿Flask框架来写的,所以FastAPI捕获异常语法也类似

def create_app():
    """
    生成FatAPI对象
    :return:
    """
    app = FastAPI()

    # 其余的一些全局配置可以写在这里 多了可以考虑拆分到其他文件夹

    # 跨域设置
    # register_cors(app)

    # 注册路由
    # register_router(app)

    # 注册捕获全局异常
    register_exception(app)

    # 请求拦截
    # register_middleware(app)
    return app

def register_static_file(app: FastAPI) -> None:
    # 自定义异常 捕获
    @app.exception_handler(UserNotFound)
    async def user_not_found_exception_handler(request: Request, exc: UserNotFound):
        """
        用户认证未找到
        :param request:
        :param exc:
        :return:
        """
        logger.error(f"token未知用户\nURL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")

        return response_code.resp_5001(message=exc.err_desc)

    # 捕获全部异常
    @app.exception_handler(Exception)
    async def all_exception_handler(request: Request, exc: Exception):
        """
        全局所有异常
        :param request:
        :param exc:
        :return:
        """
        logger.error(f"全局异常\n{request.method}URL:{request.url}\nHeaders:{request.headers}\n{traceback.format_exc()}")
        return response_code.resp_500(message="服务器内部错误")

总结

以上就是最基本的捕获异常的写法,捕获好异常,可以帮助更快更友好的排错,是接口返回格式更加规范。 注意 捕获异常函数别手误写错了,多加个s, 写成@app.exception_handlers,就会报如下异常

@app.exception_handlers(UserTokenError)
TypeError: 'dict' object is not callable

对应代码Github地址

自己改的FastAPI项目生成器 https://github.com/CoderCharm/fastapi-mysql-generator

GitHub https://github.com/CoderCharm/FastAdmin/blob/master/backend/app/api/__init__.py#L103


文章作者: 王小右
版权声明: 咳咳想白嫖文章?本文章著作权归作者所有,任何形式的转载都请注明出处。 https://www.charmcode.cn !
  目录