Skip to content

错误与异常处理 ​

用 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 状态码。

本章练习 ​

为查询任务接口设计“编号类型错误”“任务不存在”“服务内部错误”三种结果。

过关标准:能判断一个失败应该在客户端修改请求,还是由后端修改实现。