FastAPI 从入门到实战:3 分钟构建高性能异步 API

30 阅读6分钟

FastAPI 是当下 Python 异步 Web 框架的"顶流"。它基于 Starlette(异步底层)+ Pydantic(数据校验)+ Uvicorn(ASGI 服务),让你用几乎写纯 Python 的方式,自动获得类型校验、自动文档、异步高并发三大能力。本文包含可直接运行的完整代码,读完就能上手写生产级接口。


一、FastAPI 是什么?一句话定位

FastAPI 是一个现代、高性能的 Python Web 框架,专门用于构建 API

它不发模板、不做后台管理(那是 Django 的活),它只做一件事:让你用最快的速度、最少的代码、最强的类型约束,写出能扛高并发的 RESTful API

如果你之前用 Flask 写接口,你会爱上它的自动校验;如果你用 Django REST Framework,你会惊讶于它的轻量和速度。


二、FastAPI 的"三大件":核心依赖组件

FastAPI 本身并不从零造轮子,而是站在巨人肩膀上。理解它的核心依赖,才能理解它为什么快、为什么好用。

核心组件角色定位FastAPI 用它做什么
StarletteASGI 工具集 / 异步底层框架提供路由、请求/响应对象、WebSocket、后台任务、中间件等底层能力
Pydantic数据验证与序列化库利用 Python 类型注解做请求参数校验、自动转换、文档生成
UvicornASGI 服务器(基于 uvloop + httptools)运行 FastAPI 应用,支持异步事件循环,性能碾压传统的 WSGI(如 Gunicorn + Flask)

三者的关系

你的业务代码 (FastAPI)
        ↓
   路由/中间件/WS (Starlette)
        ↓
   数据校验/序列化 (Pydantic)
        ↓
   高性能 ASGI 服务 (Uvicorn)

三、为什么选 FastAPI?5 大核心优势

和传统框架对比,FastAPI 的优势不是"好一点",而是代际差距

能力FlaskDjango DRFFastAPI
异步原生支持❌ 需插件❌ 需 Channels✅ 原生 async/await
数据自动校验❌ 手动写⚠️ Serializer 类✅ Pydantic 类型注解自动校验
自动 API 文档❌ 手写 Swagger⚠️ 需配置✅ 自动生成 Swagger + ReDoc
性能(并发)低(WSGI)低(WSGI)高(ASGI,接近 Node.js/Go)
学习曲线平缓较陡极平缓(会 Python 类型注解就会用)

优势 1:类型注解即文档 + 校验

你写的 Python 类型,同时变成了:

  • 请求参数校验器(非法请求自动 422)
  • 接口文档的参数说明
  • IDE 的智能提示

优势 2:异步原生,性能拉满

基于 ASGI 和 asyncio,单实例轻松支撑数千并发连接,特别适合:

  • 高并发 API 网关
  • 微服务间大量 RPC 调用
  • 长连接(WebSocket、SSE)

优势 3:自动生成双文档

启动服务后,访问:

  • /docsSwagger UI(交互式调试,前端最爱)
  • /redocReDoc(美观的只读文档)

四、实战:15 行代码跑起来

4.1 安装

pip install fastapi uvicorn

4.2 最小 Hello World

# main.py
from fastapi import FastAPI

app = FastAPI(title="我的第一个 FastAPI 服务")

@app.get("/")
async def root():
    return {"message": "Hello FastAPI", "framework": "🚀"}

# 运行:uvicorn main:app --reload

启动命令拆解

  • main:Python 文件名(main.py)
  • app:FastAPI 实例名
  • --reload:开发模式,代码改动自动重启(生产环境别用)

浏览器访问 http://127.0.0.1:8000/docs,你会看到已经生成好的 Swagger 文档。


五、核心概念实战:路径、查询、请求体

FastAPI 的优雅之处在于:参数位置决定其行为,不需要你手动从 request 对象里扒数据。

from fastapi import FastAPI, Query, Path
from pydantic import BaseModel
from typing import Optional

app = FastAPI()

# ========== 1. 路径参数(/items/{item_id})==========
@app.get("/items/{item_id}")
async def read_item(
    item_id: int = Path(..., description="商品ID", ge=1),  # 自动校验:必须是整数,>=1
):
    return {"item_id": item_id, "type": "路径参数"}

# ========== 2. 查询参数(?skip=0&limit=10)==========
@app.get("/items/")
async def list_items(
    skip: int = Query(0, description="分页偏移"),
    limit: int = Query(10, le=100, description="每页数量,最大100"),
    q: Optional[str] = Query(None, min_length=2, description="搜索关键词"),
):
    """
    查询参数自动从 URL 中解析:
    /items/?skip=0&limit=10&q=iphone
    """
    return {"skip": skip, "limit": limit, "q": q}

# ========== 3. 请求体(POST JSON)==========
class Item(BaseModel):
    name: str = Field(..., min_length=1, max_length=50)
    price: float = Field(..., gt=0, description="必须大于0")
    is_offer: Optional[bool] = None

@app.post("/items/")
async def create_item(item: Item):
    """
    FastAPI 自动完成:
    1. 读取请求体 JSON
    2. 校验字段类型和约束
    3. 反序列化为 Item 对象
    4. 校验失败自动返回 422 Unprocessable Entity
    """
    return {
        "item_name": item.name,
        "item_price": item.price,
        "with_discount": item.is_offer
    }

运行测试

# 启动
uvicorn main:app --reload

# 测试路径参数
curl http://localhost:8000/items/42

# 测试查询参数 + 校验(limit>100 会报错)
curl "http://localhost:8000/items/?skip=0&limit=101"

# 测试 POST 请求体(合法)
curl -X POST http://localhost:8000/items/ \
  -H "Content-Type: application/json" \
  -d '{"name":"iPhone 16","price":5999.0,"is_offer":true}'

# 测试 POST 请求体(非法:price 为负数)
curl -X POST http://localhost:8000/items/ \
  -H "Content-Type: application/json" \
  -d '{"name":"iPhone","price":-100}'

六、Pydantic:FastAPI 的"隐形翅膀"

上面代码里的 BaseModel 就是 Pydantic。它给 FastAPI 带来了声明式校验的能力:

from pydantic import BaseModel, EmailStr, validator

class UserCreate(BaseModel):
    username: str
    email: EmailStr          # 自动校验邮箱格式
    password: str
    age: int = Field(..., ge=18, le=120)
    
    @validator('password')
    def password_strength(cls, v):
        if len(v) < 8:
            raise ValueError('密码至少8位')
        return v

@app.post("/users/")
async def create_user(user: UserCreate):
    # 走到这里,user 已经通过了所有校验
    return {"msg": f"用户 {user.username} 创建成功"}

不需要写 if not isinstance(...) 这种脏代码,校验失败时 FastAPI 会自动组装标准的 422 错误响应:

{
  "detail": [
    {
      "loc": ["body", "age"],
      "msg": "ensure this value is less than or equal to 120",
      "type": "value_error.number.not_le"
    }
  ]
}

七、异步实战:真正的性能武器

FastAPI 的 async 不是摆设。当你需要并发调用多个外部 API 或数据库时,性能差距会拉开:

import asyncio
import httpx
from fastapi import FastAPI

app = FastAPI()

async def fetch_data(url: str):
    async with httpx.AsyncClient() as client:
        resp = await client.get(url, timeout=5.0)
        return resp.json()

@app.get("/aggregate")
async def aggregate_data():
    """
    并发请求两个外部接口,总耗时 ≈ max(接口A耗时, 接口B耗时)
    而不是串行的 A + B
    """
    urls = [
        "https://api.github.com/users/octocat",
        "https://api.github.com/users/torvalds"
    ]
    
    # asyncio.gather 并发执行
    results = await asyncio.gather(
        *[fetch_data(url) for url in urls],
        return_exceptions=True
    )
    
    return {"data": results}

⚠️ 注意:如果你的代码里调用了同步阻塞库(如 requestspymysql),必须改用异步版本(httpxaiomysql),否则 async 形同虚设。


八、生产环境部署

开发用 uvicorn main:app --reload,生产环境推荐 Gunicorn + Uvicorn Worker

# 安装
pip install gunicorn

# 启动:4 个 worker 进程,每个进程内是 uvloop 异步循环
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

或者直接用 Uvicorn 多进程模式:

uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

九、总结:FastAPI 适合什么场景?

场景推荐指数原因
微服务 API 网关⭐⭐⭐⭐⭐异步高并发,天然适合 I/O 密集
机器学习模型服务⭐⭐⭐⭐⭐快速暴露模型接口,自动校验输入特征
后台管理 + 复杂业务⭐⭐⭐无内置 ORM/Admin,需配合 SQLAlchemy
纯静态网站/SSR⭐⭐用 Next.js/Nuxt 更合适

学习路径建议

Day 1: 安装 → Hello World → 路径/查询/请求体参数
Day 2: Pydantic 模型 → 嵌套模型 → 响应模型控制
Day 3: 依赖注入(Depends) → 数据库连接池 → 异步 ORM(SQLAlchemy 2.0)
Day 4: 认证(OAuth2/JWT) → 中间件 → CORS
Day 5: 后台任务 → WebSocket → 部署(Gunicorn + Docker)