FastAPI中Pydantic校验抛ValueError触发内部服务器错误如何解决
问题根因
- Pydantic的validator中抛出的
ValueError会被自动封装进Pydantic原生的ValidationError错误对象中,但FastAPI通过Depends()绑定路径参数的Pydantic模型时,默认不会主动拦截这类校验异常,未捕获的异常会被判定为服务端内部错误,因此返回500状态码。 - 日志中出现的
ValueError() takes no keyword arguments属于旧版本Pydantic的已知兼容性问题,升级到Pydantic 1.9+或2.x版本即可消除该报错。
解决方案
无需修改validator中抛出ValueError的逻辑,只需新增全局异常处理器拦截Pydantic的校验错误,转为自定义响应即可:
from fastapi import FastAPI, Request from fastapi.responses import JSONResponse from pydantic import BaseModel, validator, ValidationError from fastapi import Depends app = FastAPI() # 新增全局Pydantic校验异常拦截器 @app.exception_handler(ValidationError) async def handle_pydantic_validation_err(request: Request, exc: ValidationError): # 提取validator中抛出的ValueError错误信息 error_msg = exc.errors()[0]["msg"] return JSONResponse( status_code=400, # 自定义返回状态码 content={"detail": error_msg} ) class RankInput(BaseModel): rank: int @validator('rank') def check_if_value_in_range(cls, v): if not 0 < v < 1000001: # 保持原有抛出ValueError的逻辑不变 raise ValueError("Rank Value Must be within range (0,1000000)") return v def get_info_by_rank(rank): return rank @app.get('/rank/{rank}') async def get_rank(value: RankInput = Depends()): result = get_info_by_rank(value.rank) return result
如果不想配置全局异常处理器,也可以单独封装依赖函数处理校验逻辑:
from fastapi import HTTPException def validate_rank_input(rank: int): try: return RankInput(rank=rank) except ValidationError as e: raise HTTPException(status_code=400, detail=e.errors()[0]["msg"]) @app.get('/rank/{rank}') async def get_rank(value: RankInput = Depends(validate_rank_input)): result = get_info_by_rank(value.rank) return result
内容的提问来源于stack exchange,提问作者Rajath Rao - Software Engineer
相关产品推荐
相关产品推荐

