FastAPI 框架
问题
FastAPI 的核心特性是什么?为什么说它是"现代 Python Web 框架"?
答案
FastAPI 基于 Starlette 和 Pydantic,原生支持 async/await、自动生成 OpenAPI 文档、类型安全的请求校验。
基础应用
from fastapi import FastAPI, Query, Path, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title="User API", version="1.0.0")
# Pydantic 模型自动校验请求体
class UserCreate(BaseModel):
name: str = Field(..., min_length=1, max_length=50)
email: str = Field(..., pattern=r"^[\w.-]+@[\w.-]+\.\w+$")
age: int = Field(ge=0, le=150)
class UserResponse(BaseModel):
id: int
name: str
email: str
# 路径参数 + 查询参数 + 自动文档
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(
user_id: int = Path(..., ge=1),
include_email: bool = Query(default=True),
):
user = await fetch_user(user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(user: UserCreate):
return await save_user(user)
依赖注入
FastAPI 的依赖注入系统是其最强大的特性之一:
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
# 数据库会话依赖
async def get_db() -> AsyncGenerator[AsyncSession, None]:
async with async_session() as session:
yield session
# 认证依赖
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db),
) -> User:
user = await verify_token(token, db)
if not user:
raise HTTPException(status_code=401)
return user
# 使用依赖——自动注入 db 和 user
@app.get("/profile")
async def profile(
user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
return await get_profile(db, user.id)
中间件与生命周期
from contextlib import asynccontextmanager
# 应用生命周期(启动/关闭)
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动时初始化
await init_db()
yield
# 关闭时清理
await close_db()
app = FastAPI(lifespan=lifespan)
# 中间件
@app.middleware("http")
async def add_timing(request, call_next):
start = time.time()
response = await call_next(request)
response.headers["X-Process-Time"] = str(time.time() - start)
return response
框架对比
| 特性 | FastAPI | Flask | Django |
|---|---|---|---|
| 异步支持 | 原生 async | 需要扩展 | 3.1+ 部分支持 |
| 类型校验 | Pydantic 自动 | 手动 | Serializer |
| API 文档 | 自动生成 Swagger/ReDoc | 需扩展 | 需 DRF |
| 性能 | 高(Uvicorn/Starlette) | 中 | 中 |
| 学习曲线 | 低 | 低 | 高 |
常见面试问题
Q1: FastAPI 为什么性能高?
答案:
- ASGI 原生:基于 Starlette,利用
uvloop和httptools高性能 C 扩展 - 异步 I/O:原生 async/await,非阻塞处理并发请求
- Pydantic v2:核心校验逻辑用 Rust 编写,比 v1 快 5-50 倍
- 无 ORM 绑定:不强制绑定 ORM,避免不必要的抽象开销
Q2: FastAPI 的依赖注入和 Spring 的区别?
答案:
FastAPI 依赖注入是函数级别的,每个请求独立解析依赖树。Spring 是 Bean 容器级别的,启动时注入。FastAPI 更轻量,适合无状态 API;Spring 更完整,适合复杂企业应用。
Q3: 如何处理 FastAPI 中的后台任务?
答案:
from fastapi import BackgroundTasks
@app.post("/send-email")
async def send_email(bg: BackgroundTasks):
bg.add_task(send_email_task, "user@example.com")
return {"message": "Email queued"}
对于复杂任务,应使用 Celery 等分布式任务队列。
Q4: FastAPI 如何做认证?
答案:
FastAPI 内置 OAuth2 支持:
from fastapi.security import OAuth2PasswordBearer
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.get("/protected")
async def protected(token: str = Depends(oauth2_scheme)):
# token 自动从 Authorization: Bearer xxx 提取
return verify_and_decode(token)
Q5: Pydantic v1 和 v2 的主要区别?
答案:
| 特性 | Pydantic v1 | Pydantic v2 |
|---|---|---|
| 核心引擎 | 纯 Python | Rust (pydantic-core) |
| 性能 | 基准 | 快 5-50x |
| 严格模式 | 无 | model_config = ConfigDict(strict=True) |
| 序列化 | .dict() | .model_dump() |
| 校验器 | @validator | @field_validator |