引言:为什么选择FastAPI?

在现代软件开发中,API(应用程序编程接口)无处不在。它是连接不同服务、不同应用的桥梁。你想做的几乎任何事——从获取天气数据,到让AI模型进行推理,再到将数据存入数据库——通常都是通过调用一个API来完成的。

那么,如果你想用Python来创建一个API呢?

在过去,开发者可能会选择Flask或Django。但近年来,一个名为FastAPI的新星迅速崛起,并成为许多开发者的首选。原因何在?

  • Fast (快速): 它的性能极高,与Node.js和Go等语言的框架不相上下。这得益于它底层的Starlette(用于Web部分)和Pydantic(用于数据部分)。
  • Easy (易用): 框架学习曲线平缓,代码量少,非常直观。
  • 自动文档: 这是FastAPI最令人惊艳的特性之一。你只需编写API代码,它就能自动为你生成两种交互式的API文档界面(Swagger UI 和 Redoc)。你不再需要手动编写和维护API文档!
  • 智能校验: 基于Python的类型提示,FastAPI(通过Pydantic)能自动对接收到的数据进行校验和转换,确保你的API收到的都是格式正确的数据。

环境准备

要运行FastAPI,你需要两样东西:

  1. FastAPI库本身
  2. 一个ASGI服务器,用来运行你的应用,比如uvicorn
# 安装FastAPI和uvicorn
pip install fastapi "uvicorn[standard]"

你的第一个API

让我们创建一个最简单的API。新建一个名为main.py的文件:

# main.py
from fastapi import FastAPI

# 1. 创建一个FastAPI实例
app = FastAPI()

# 2. 定义一个“路径操作” (Path Operation)
@app.get("/")
def read_root():
    return {"message": "你好, FastAPI!"}

@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

代码解读:

  • app = FastAPI(): 创建了一个应用实例。
  • @app.get("/"): 这是一个“装饰器”,它告诉FastAPI,下面这个函数负责处理发往路径/GET请求。
  • @app.get("/items/{item_id}"): 定义了另一个路径。这里的{item_id}路径参数,意味着你可以访问像/items/5这样的URL。
  • item_id: int: FastAPI利用Python的类型提示,自动将URL中的item_id(此时是字符串"5")转换并校验为整数。如果访问/items/foo,它会自动返回一个清晰的错误。
  • q: str | None = None: 这是一个查询参数。你可以访问/items/5?q=somequery。因为它被声明为可选的(None),所以如果URL中不提供q,也不会报错。

运行你的API服务器

main.py文件所在的目录下,打开终端,运行:

uvicorn main:app --reload
  • main: 指的是main.py文件。
  • app: 指的是我们在代码中创建的app = FastAPI()对象。
  • --reload: 这个标志非常有用,它让服务器在你的代码文件被修改后自动重启。

服务器启动后,你会看到类似这样的输出:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

见证奇迹:自动交互式文档

现在,打开你的浏览器,做两件事:

  1. 访问 http://127.0.0.1:8000/docs 你会看到一个Swagger UI界面。这是一个交互式的API文档。它列出了你所有的API端点(我们刚才定义的//items/{item_id}),你可以直接在页面上对它们进行测试!

  2. 访问 http://127.0.0.1:8000/redoc 你会看到另一种风格的文档界面 Redoc

这个特性是革命性的。你只需要专注于编写业务逻辑,文档就自动生成了,并且永远和你的代码保持同步。

使用Pydantic进行数据校验

FastAPI的超能力很大程度上来自于Pydantic库。你可以用它来定义复杂的数据结构,FastAPI会用它来做请求体(Request Body)的校验。

假设我们想创建一个POST请求来接收一个物品的数据。

修改main.py:

from fastapi import FastAPI
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

app = FastAPI()

@app.post("/items/")
def create_item(item: Item):
    return {"item_name": item.name, "price_with_tax": item.price + (item.tax or 0)}

# ... 保留之前的 .get 请求 ...

代码解读:

  • 我们从pydantic导入BaseModel并创建了一个Item类。
  • 这个类定义了我们期望从请求中收到的JSON对象的“形状”:必须有一个字符串name,一个浮点数price,以及两个可选的字段。
  • create_item函数中,我们把参数item的类型声明为我们刚创建的Item模型。

现在,FastAPI会自动:

  1. 从POST请求中读取JSON请求体。
  2. 校验它是否符合Item模型的结构。
    • 如果name缺失或不是字符串,price不是数字,它会自动返回一个指明具体错误的422 Unprocessable Entity响应。
  3. 如果数据有效,它会将JSON转换为一个Item对象,你可以在函数中直接使用item.name这样的方式来访问数据。

你可以再次访问/docs,会发现新的POST /items/端点已经出现。你甚至可以直接在文档里构建一个JSON来测试它。

总结

你刚刚已经用Python构建了一个健壮、高性能、自带文档的现代API。

  • 你学会了使用@app.get, @app.post等装饰器定义API路径。
  • 你理解了路径参数和查询参数的区别。
  • 你掌握了使用Pydantic模型来定义和校验请求数据的强大功能。
  • 你体验了uvicorn如何运行你的应用,以及--reload带来的便利。

FastAPI让创建高质量的Web API变得前所未有的简单和愉快。在你的下一个需要提供接口的项目中,给FastAPI一个机会吧!