FastAPI 后端开发实战教程:从入门到生产部署
FastAPI 是现代 Python Web 开发的性能王者,基于 Starlette 和 Pydantic 构建,自动生成交互式文档,支持类型提示和异步编程。本教程将带你从零开始掌握 FastAPI 的核心特性和最佳实践。
一、FastAPI 简介与核心优势
FastAPI 是一个现代、高性能的 Python Web 框架,专为构建 API 而设计。自 2018 年发布以来,它迅速成为 Python 后端开发的热门选择,被 Netflix、Uber、Microsoft 等知名公司采用。
1.1 为什么选择 FastAPI?
FastAPI 的核心设计理念是"快速、开发者友好和类型驱动",它具有以下突出优势:
- 极致性能:基于 Starlette(Web 部分)和 Pydantic(数据部分)构建,性能与 Node.js 和 Go 相当,是 Python 中最快的 Web 框架之一
- 自动文档生成:通过类型注解自动生成交互式 API 文档(Swagger UI 和 ReDoc),无需手动编写文档
- 类型驱动开发:利用 Python 类型提示自动进行数据验证、序列化和反序列化,在开发时捕获错误
- 原生异步支持:完全支持 async/await,在处理 I/O 密集型任务时表现出色
- 编辑器支持:完善的类型提示让 IDE 能提供出色的自动补全和错误检查
1.2 典型应用场景
FastAPI 适用于多种场景:
- 构建微服务架构中的数据接口
- 开发高并发的实时数据处理服务
- 为移动应用或前端提供后端 API
- AI 模型服务化部署
- 数据处理管道和 ETL 系统
二、环境搭建与第一个应用
2.1 环境准备
确保你的系统安装了 Python 3.8 或更高版本。推荐使用虚拟环境隔离项目依赖:
# 创建虚拟环境 python3 -m venv fastapi-env # 激活虚拟环境 source fastapi-env/bin/activate # macOS/Linux # fastapi-env\Scripts\activate # Windows # 安装 FastAPI 和 Uvicorn pip install "fastapi[standard]"
fastapi[standard] 会安装 FastAPI 及其所有可选依赖,包括 Uvicorn ASGI 服务器。
2.2 编写第一个 API
创建 main.py 文件,编写一个简单的 Hello World API:
from fastapi import FastAPI
# 创建 FastAPI 应用实例
app = FastAPI(
title="我的第一个 API",
description="FastAPI 入门示例",
version="1.0.0"
)
# 定义根路径的 GET 请求处理
@app.get("/")
async def read_root():
"""返回欢迎消息"""
return {"message": "Hello, FastAPI!", "status": "success"}
# 带路径参数的路由
@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
"""
获取指定 ID 的项目
- item_id: 项目 ID(整数类型,自动验证)
- q: 可选的查询参数
"""
result = {"item_id": item_id}
if q:
result.update({"q": q})
return result
2.3 运行应用
使用 Uvicorn 运行应用:
uvicorn main:app --reload
参数说明:
main:Python 文件名(main.py)app:FastAPI 实例名--reload:热重载,代码修改后自动重启
启动后访问 http://127.0.0.1:8000 即可看到返回的 JSON 数据。
2.4 自动生成的交互式文档
FastAPI 最大的亮点之一是自动生成的 API 文档:
- Swagger UI:
http://127.0.0.1:8000/docs- 可直接在浏览器中测试 API - ReDoc:
http://127.0.0.1:8000/redoc- 美观的文档展示界面
三、核心概念详解
3.1 路径参数
路径参数是从 URL 路径中提取的值,FastAPI 会自动进行类型转换和验证:
from fastapi import FastAPI, HTTPException
app = FastAPI()
# 模拟数据库
items_db = {
1: {"name": "Python 编程", "price": 59.9},
2: {"name": "FastAPI 实战", "price": 79.9},
}
@app.get("/items/{item_id}")
async def get_item(item_id: int):
"""根据 ID 获取商品信息"""
if item_id not in items_db:
raise HTTPException(status_code=404, detail="商品不存在")
return {
"item_id": item_id,
"item": items_db[item_id]
}
# 支持路径参数的枚举类型
from enum import Enum
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
"""获取指定模型信息"""
return {
"model": model_name,
"message": f"这是 {model_name.value} 模型"
}
3.2 查询参数
查询参数是 URL 中 ? 后面的键值对,常用于过滤、分页等场景:
from typing import Optional, List
@app.get("/products/")
async def list_products(
skip: int = 0, # 分页偏移量,默认 0
limit: int = 10, # 每页数量,默认 10
category: Optional[str] = None, # 可选的分类过滤
min_price: float = 0, # 最低价格
max_price: float = 10000 # 最高价格
):
"""
商品列表接口,支持分页和过滤
访问示例:/products/?skip=0&limit=5&category=books
"""
# 模拟数据库查询
products = [
{"id": 1, "name": "商品A", "price": 99.9},
{"id": 2, "name": "商品B", "price": 199.9},
{"id": 3, "name": "商品C", "price": 29.9},
]
return {
"skip": skip,
"limit": limit,
"total": len(products),
"products": products[skip:skip + limit]
}
3.3 请求体与 Pydantic 模型
对于 POST、PUT 等请求,使用 Pydantic 模型定义请求体结构和验证规则:
from pydantic import BaseModel, Field, validator
from datetime import datetime
from typing import Optional
# 定义数据模型
class ProductCreate(BaseModel):
"""创建商品的数据模型"""
name: str = Field(..., min_length=2, max_length=100, description="商品名称")
price: float = Field(..., gt=0, description="商品价格,必须大于 0")
description: Optional[str] = Field(None, max_length=500, description="商品描述")
category: str = Field(..., description="商品分类")
stock: int = Field(default=0, ge=0, description="库存数量")
@validator("name")
def name_must_not_contain_special_chars(cls, v):
if any(char in v for char in ["<", ">", "&"]):
raise ValueError("商品名称不能包含特殊字符")
return v
class ProductResponse(ProductCreate):
"""商品响应模型"""
id: int
created_at: datetime
updated_at: datetime
# 模拟数据库
products_db = []
product_id_counter = 0
@app.post("/products/", response_model=ProductResponse, status_code=201)
async def create_product(product: ProductCreate):
"""
创建新商品
FastAPI 会自动:
1. 验证请求数据是否符合 ProductCreate 模型
2. 转换数据类型
3. 返回清晰的错误信息
"""
global product_id_counter
product_id_counter += 1
product_dict = product.dict()
product_dict.update({
"id": product_id_counter,
"created_at": datetime.now(),
"updated_at": datetime.now()
})
products_db.append(product_dict)
return product_dict
四、依赖注入系统
依赖注入是 FastAPI 最强大的特性之一,可以优雅地处理数据库连接、认证、权限等通用逻辑:
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from typing import Generator
# 模拟数据库连接
class Database:
def __init__(self):
self.connected = True
def query(self, sql: str):
return f"查询结果: {sql}"
def close(self):
self.connected = False
# 数据库依赖
def get_db() -> Generator:
"""获取数据库连接,使用 yield 确保资源释放"""
db = Database()
try:
yield db
finally:
db.close() # 请求结束后自动关闭连接
# 认证依赖
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security)
):
"""获取当前用户"""
token = credentials.credentials
# 模拟 token 验证
if token != "valid-token":
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="无效的认证凭证"
)
return {"id": 1, "username": "admin"}
# 使用依赖的路由
@app.get("/users/me")
async def read_users_me(
current_user: dict = Depends(get_current_user),
db: Database = Depends(get_db)
):
"""
获取当前用户信息
自动注入:
- current_user: 经过认证的用户
- db: 数据库连接
"""
return {
"user": current_user,
"db_status": "connected" if db.connected else "disconnected"
}
五、异步编程最佳实践
FastAPI 完全支持异步编程,正确使用 async/await 可以显著提升性能:
import httpx
import asyncio
from typing import List
# 异步 HTTP 客户端
async def fetch_url(url: str) -> dict:
"""异步获取 URL 内容"""
async with httpx.AsyncClient() as client:
response = await client.get(url)
return {"url": url, "status": response.status_code}
@app.get("/batch-fetch")
async def batch_fetch_urls(urls: List[str]):
"""
并发获取多个 URL
使用 asyncio.gather 实现并发请求
"""
tasks = [fetch_url(url) for url in urls]
results = await asyncio.gather(*tasks, return_exceptions=True)
return {
"total": len(urls),
"results": results
}
5.1 何时使用 async/await
- 使用 async def:网络请求、数据库查询、文件 I/O 等 I/O 密集型操作
- 使用普通 def:CPU 密集型计算,FastAPI 会自动放到线程池执行
- 避免在 async 中执行阻塞操作:如 time.sleep()、同步的数据库调用
六、错误处理与异常
FastAPI 提供了完善的错误处理机制:
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
app = FastAPI()
# 自定义异常
class ItemNotFoundException(Exception):
def __init__(self, item_id: int):
self.item_id = item_id
# 全局异常处理器
@app.exception_handler(ItemNotFoundException)
async def item_not_found_handler(request: Request, exc: ItemNotFoundException):
"""自定义异常处理"""
return JSONResponse(
status_code=404,
content={
"error": "ITEM_NOT_FOUND",
"message": f"商品 ID {exc.item_id} 不存在",
"path": request.url.path
}
)
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
"""请求验证错误处理"""
return JSONResponse(
status_code=422,
content={
"error": "VALIDATION_ERROR",
"message": "请求数据验证失败",
"details": exc.errors()
}
)
@app.get("/items/{item_id}")
async def get_item(item_id: int):
"""可能抛出自定义异常的接口"""
if item_id > 100:
raise ItemNotFoundException(item_id)
if item_id < 0:
raise HTTPException(
status_code=400,
detail="商品 ID 不能为负数"
)
return {"item_id": item_id, "name": "示例商品"}
七、项目结构最佳实践
对于中大型项目,推荐使用清晰的目录结构:
project/ ├── app/ │ ├── __init__.py │ ├── main.py # 应用入口 │ ├── config.py # 配置管理 │ ├── dependencies.py # 公共依赖 │ ├── routers/ # 路由模块 │ │ ├── __init__.py │ │ ├── users.py │ │ └── products.py │ ├── models/ # 数据模型 │ │ ├── __init__.py │ │ ├── user.py │ │ └── product.py │ ├── schemas/ # Pydantic 模型 │ │ ├── __init__.py │ │ ├── user.py │ │ └── product.py │ ├── services/ # 业务逻辑 │ │ ├── __init__.py │ │ └── user_service.py │ └── utils/ # 工具函数 │ └── __init__.py ├── tests/ # 测试文件 │ └── test_main.py ├── alembic/ # 数据库迁移 ├── .env # 环境变量 ├── requirements.txt └── Dockerfile
7.1 配置管理
# app/config.py
from pydantic_settings import BaseSettings
from functools import lru_cache
class Settings(BaseSettings):
"""应用配置"""
app_name: str = "FastAPI 应用"
debug: bool = False
# 数据库配置
database_url: str
# 安全配置
secret_key: str
access_token_expire_minutes: int = 30
class Config:
env_file = ".env"
@lru_cache()
def get_settings() -> Settings:
"""获取配置(缓存)"""
return Settings()
# 在路由中使用
@app.get("/info")
async def app_info(settings: Settings = Depends(get_settings)):
return {"app_name": settings.app_name}
八、部署与生产实践
8.1 使用 Gunicorn + Uvicorn
# 安装
pip install gunicorn uvicorn[standard]
# 启动命令(多 worker)
gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--timeout 120
8.2 Docker 部署
# Dockerfile FROM python:3.11-slim WORKDIR /app # 安装依赖 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY ./app ./app # 非 root 用户运行 RUN useradd -m appuser && chown -R appuser:appuser /app USER appuser # 启动命令 CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "-b", "0.0.0.0:8000"]
8.3 生产环境安全配置
from fastapi import FastAPI
# 生产环境禁用文档
app = FastAPI(
title="生产 API",
docs_url=None, # 禁用 Swagger UI
redoc_url=None, # 禁用 ReDoc
openapi_url=None # 禁用 OpenAPI schema
)
# 或者通过环境变量控制
import os
DEBUG = os.getenv("DEBUG", "false").lower() == "true"
app = FastAPI(
docs_url="/docs" if DEBUG else None,
redoc_url="/redoc" if DEBUG else None
)
总结
FastAPI 凭借其高性能、自动文档生成、类型安全等特性,已成为 Python Web 开发的首选框架。本教程涵盖了从环境搭建到生产部署的完整流程,核心要点包括:
- 类型驱动:利用 Pydantic 模型实现数据验证和文档生成
- 异步优先:正确使用 async/await 提升 I/O 性能
- 依赖注入:优雅地管理共享逻辑和资源
- 项目结构:清晰的模块划分,便于维护和扩展
- 生产部署:多 worker、容器化、安全配置
掌握这些核心概念后,你可以快速构建高性能、可维护的 API 服务。FastAPI 的生态还在不断发展,结合 SQLAlchemy 2.0、Pydantic v2 等现代工具,Python 后端开发体验已经达到新的高度。
本文链接:https://www.kkkliao.cn/?id=987 转载需授权!
版权声明:本文由廖万里的博客发布,如需转载请注明出处。



手机流量卡
免费领卡
号卡合伙人
产品服务
关于本站
