错误与异常处理
用 raise HTTPException 表达预期失败
完整示例:
python
from fastapi import FastAPI, HTTPException
app = FastAPI()
books = {1: {"id": 1, "title": "Python 基础"}}
@app.get("/books/{book_id}")
def read_book(book_id: int):
book = books.get(book_id)
if book is None:
raise HTTPException(status_code=404, detail="图书不存在")
return book访问 /books/999 时,会得到 404 和类似下面的 JSON:
json
{ "detail": "图书不存在" }要使用 raise,因为这是抛出异常并结束当前处理流程;return HTTPException(...) 是返回异常对象,不能正确表达预期的 HTTP 错误。官方错误处理说明
如何阅读 422
典型错误中可能出现:
json
{
"detail": [
{
"loc": ["body", "price"],
"msg": "Input should be greater than 0",
"type": "greater_than"
}
]
}不同版本可能包含更多字段或略有不同的描述。优先读:
loc:错误位置。body是请求体,query是查询参数,path是路径参数。msg:给人阅读的原因。type:错误类型,方便程序判断。
先核对位置,再核对字段名、字段类型和请求结构。不要看到 422 就修改端口或重装 FastAPI。
业务错误与程序错误
“图书不存在”是业务上可以预见的情况,应有合适的状态码。“变量拼错了”是程序错误,应看服务器日志并修复代码。
不要用一个宽泛的 except Exception 把所有错误都转换为 200;这会让调用方以为操作成功,也会掩盖真正的问题。
自定义异常处理器
追加到本章完整示例:
python
from fastapi import Request
from fastapi.responses import JSONResponse
class BusinessError(Exception):
def __init__(self, message: str):
self.message = message
@app.exception_handler(BusinessError)
async def handle_business_error(request: Request, exc: BusinessError):
return JSONResponse(
status_code=400,
content={"code": "BUSINESS_ERROR", "message": exc.message},
)
@app.get("/business-error-example")
def business_error_example():
raise BusinessError("当前状态不允许执行此操作")先掌握默认错误行为,再考虑统一格式。统一格式时也应保留有意义的 HTTP 状态码。
本章练习
为查询任务接口设计“编号类型错误”“任务不存在”“服务内部错误”三种结果。
过关标准:能判断一个失败应该在客户端修改请求,还是由后端修改实现。