异常处理
统一捕获处理异常,使得代码更加完善,健壮。
框架内置了一些异常,当然也可以自己定义异常然后捕获处理。
完全可以参考官网(超喜欢这种风格的文档):
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"全局异
{request.method}URL{request.url}
Headers:{request.headers}
{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"用户认证异常
URL:{request.url}
Headers:{request.headers}
{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未知用户
URL:{request.url}
Headers:{request.headers}
{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"全局异常
{request.method}URL:{request.url}
Headers:{request.headers}
{traceback.format_exc()}")
return response_code.resp_500(message="服务器内部错误")
异常详情
上一章博客有提过,使用traceback
打印详细异常
import traceback
logger.error(traceback.format_exc())
总结
以上就是最基本的捕获异常的写法,捕获好异常,可以帮助更快更友好的排错,是接口返回格式更加规范。
注意
捕获异常函数别手误写错了,多加个s
, 写成@app.exception_handlers,就会报如下异常
@app.exception_handlers(UserTokenError)
TypeError: 'dict' object is not callable
对应代码Github地址
见个人网站 https://www.charmcode.cn/article/2020-07-19_fastapi_exception