Superpowers + Claude Code 实战:从零搭建 FastAPI 认证脚手架实录
以 Superpowers 七阶段工作流为纲,借助 Claude Code 和 GLM 5.1 全程驱动,手把手构建一个可直接投产的 FastAPI + SQLAlchemy + Redis RESTful API 服务。
核心概念速览
这是什么?
这是一篇动手操作实录。我打开 Claude Code,使用 GLM 5.1 作为 Coding Plan 供应方,严格遵循 Superpowers 工作流,从空白项目开始,搭建一套完整的 Python FastAPI Server 脚手架。
最终交付物:一个提供用户注册、登录鉴权及受保护端点的 RESTful API 服务,可以直接作为任何 Python 后端项目的初始骨架。
为什么选择 Python?
2025–2026 年,Python 在 API 服务领域的采用率持续走高。FastAPI 的出现彻底扭转了“Python 不适合高性能 API”的旧印象:
- • 异步原生:基于 Starlette 与 Pydantic,天生支持 async/await
- • 自动文档:OpenAPI + Swagger UI 开箱即用,前端协作几乎零开销
- • 类型安全:Pydantic v2 完成请求验证与序列化,运行时的类型检查能力甚至超过 Go 的 struct tag
- • 生态无敌:覆盖 ML/AI、数据处理、自动运维,一站式解决能力无出其右
能解决哪些痛点?
- • 想用 FastAPI 启动后端项目但缺乏完整参考实现
- • 看过 FastAPI 官网教程,却不清楚生产级项目如何组织
- • 需要一套可复用的 Python API 脚手架作为新项目的起点
- • 想在 Go、Spring Boot、Rust、Python 这四种语言的脚手架间做横向对比
ClaudeCode 编码执行
FastAPI Server 脚手架
GLM 5.1 Coding Plan
Superpowers 工程纪律
注册/登录/鉴权
四层架构
MySQL+Redis
技术栈选型
为何选 FastAPI 而非 Flask 或 Django?
| 框架 | 异步支持 | 自动文档 | 性能 | 学习曲线 |
|---|---|---|---|---|
| FastAPI | 原生 async | OpenAPI 内置 | 接近 Go/Node | 低 |
| Flask 3.x | 需要异步扩展 | 手动集成 | 中等 | 低 |
| Django 5.x | 支持 ASGI | 需 DRF + drf-spectacular | 中等 | 高 |
FastAPI 如今已是 Python API 开发的事实标准。Netflix、Microsoft、Uber 都在生产环境使用它。具体原因:
-
- 性能接近 Go:TechEmpower 基准测试中,FastAPI 长期在 Python 框架中排名第一
-
- 自动 API 文档:编写完接口即生成 Swagger UI,前端对接效率翻倍
-
- Pydantic v2:请求校验、响应序列化、类型推导一步到位
-
- uvicorn ASGI:基于 uvloop 的事件循环,吞吐量比 gunicorn + WSGI 高 3–5 倍
组件选型清单
| 组件 | 选择 | 理由 |
|---|---|---|
| Web 框架 | FastAPI 0.115+ | 异步原生,自动文档,深度集成 Pydantic |
| ORM | SQLAlchemy 2.0 | Python 生态最成熟的 ORM,全面支持异步 |
| 数据库驱动 | aiomysql | MySQL 异步驱动,与 SQLAlchemy async 协作 |
| 数据库 | MySQL 8 | 国内运维人才储备足,各大云厂商均有成熟托管方案 |
| 缓存 | redis‑py 5.x | 官方维护,原生支持 async,内置连接池管理 |
| 认证 | PyJWT 2.x + passlib | JWT 签发 + bcrypt 哈希,行业标准组合 |
| 数据验证 | Pydantic v2 | FastAPI 内置,速度比 marshmallow 快 5–50 倍 |
| ASGI 服务器 | uvicorn | 基于 uvloop,生产级性能 |
为什么用 SQLAlchemy 2.0 而不是 Tortoise ORM?
SQLAlchemy 2.0 引入了全新的 select() API 和原生异步支持,书写体验比 1.x 大幅提升。坚持用它的理由如下:
-
- SQLAlchemy 是 Python ORM 的“标准答案”,遇到问题时在 Stack Overflow 上的答案最多
-
- 2.0 的 async session 与 type hint 支持让开发体验接近 Django ORM
-
- Alembic 数据迁移工具链成熟,生产环境可靠
Redis 承担两种职责
和 Go 脚手架类似,Redis 也肩负两个任务:
-
- Token 缓存:JWT 签发后写入 Redis(key 格式:
token:{user_id},TTL 24 小时),登出时删除
- Token 缓存:JWT 签发后写入 Redis(key 格式:
-
- 接口限流:基于 IP 的滑动窗口限流,防止暴力注册与登录
架构一览
Token 验证
401
客户端
FastAPI Router
公开路由 /register /login
Auth 依赖注入
Router 层
拒绝访问
Service 层
Repository 层
MySQL
Redis
经典的四层架构:Router 负责路由与请求校验,Service 专注于业务逻辑,Repository 封装数据访问。FastAPI 的 Depends() 机制让依赖注入比 Go 的手写中间件更简洁优雅。
Superpowers 头脑风暴
一切从 /superpowers:brainstorming 开始。
第一轮:启动
👤 我:我要搭建一个 Python FastAPI Server 脚手架,使用 FastAPI + SQLAlchemy + MySQL + Redis,包含用户注册、登录、JWT 鉴权。
Claude Code 进入头脑风暴阶段:
🤖 Claude Code:收到。在正式动手前,先确认几个关键设计决策。
- • 问题 1:Python 版本——3.11 还是 3.12?3.12 在性能提升和类型语法方面更优。
- • 问题 2:ORM 风格——SQLAlchemy 2.0 支持 Dataclass 声明式与传统 Mapper 式,倾向哪种?
- • 问题 3:项目结构——采用
src/布局还是扁平式?是否需要pyproject.toml?
👤 我:Python 3.12。声明式(Mapped + mapped_column)。扁平布局 + pyproject.toml。
第二轮:架构推导
🤖 Claude Code:明白。推导出如下分层结构:
app/
├── main.py # FastAPI 入口,管理 lifespan
├── config.py # Pydantic Settings 配置
├── database.py # SQLAlchemy 异步引擎及会话
├── model/
│ └── user.py # 用户 ORM 模型
├── schema/
│ └── user.py # Pydantic 请求/响应 schema
├── repository/
│ └── user.py # 数据库操作
├── service/
│ └── user.py # 业务逻辑
├── router/
│ └── user.py # API 路由
├── middleware/
│ └── auth.py # JWT 认证依赖
└── deps.py # 公共依赖注入
🤖 Claude Code:
- • 问题 4:Schema 命名——Pydantic 模型用
UserCreate/UserLogin还是RegisterRequest/LoginRequest?- • 问题 5:虚拟环境——使用
venv还是uv?
👤 我:用
UserCreate/UserLogin/UserResponse。用 Python 内置venv。
第三轮:数据库设计
🤖 Claude Code:用户表结构如下:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | INTEGER | 主键自增 |
| username | VARCHAR(64) | 唯一索引 |
| password | VARCHAR(128) | bcrypt 哈希 |
| created_at | DATETIME | 创建时间 |
| updated_at | DATETIME | 更新时间 |
第四轮:JWT 认证流程
🤖 Claude Code:确认 JWT 认证流程:
-
- 用户调用
/api/login,密码验证通过后签发 JWT
- 用户调用
-
- JWT 存入 Redis(key:
token:{user_id},TTL:24h)
- JWT 存入 Redis(key:
-
- 后续请求在 Authorization header 中携带 Bearer Token
-
- FastAPI 依赖注入解析 JWT → 查询 Redis 验证 → 放行或返回 401
-
- 登出时移除 Redis 中对应的 key
👤 我:确认。开始吧。
Writing Plans
头脑风暴通过后,触发写作计划:
👤 我:/superpowers:writing-plans
PLAN: Python FastAPI Server 脚手架
==================================
Task 1: 项目初始化
- python3 -m venv venv
- pyproject.toml 配置依赖
- 创建 app/ 目录结构
Task 2: 配置层 + 数据库连接
- config.py Pydantic Settings 加载环境变量
- database.py 异步引擎 + AsyncSessionLocal
Task 3: 数据模型
- model/user.py User ORM 模型(Mapped + mapped_column)
Task 4: Pydantic Schema
- schema/user.py UserCreate / UserLogin / UserResponse
Task 5: Repository 层
- repository/user.py 异步 create_user / get_by_username
Task 6: Service 层
- service/user.py register / login(bcrypt + JWT + Redis)
Task 7: 认证依赖
- middleware/auth.py get_current_user(解析 JWT + Redis 验证)
Task 8: Router 层
- router/user.py register / login / echo 三个接口
Task 9: 启动入口
- main.py FastAPI app + lifespan + 路由挂载
Task 10: 编译验证 + 接口测试
- 启动服务 + curl 测试注册、登录、鉴权
👤 我:确认,开始执行。
Git Worktree
# AI 自动执行
🌳 创建隔离工作区: feature/fastapi-server
🔀 切换到新分支: feature/fastapi-server
📁 初始化 Python 虚拟环境: python3 -m venv venv
✅ 工作区就绪
Subagent 驱动开发
以下是 4 个关键代码片段的完整实录。
片段 1:数据模型(app/model/user.py)
子 Agent 3 号执行 Task 3,完成 User ORM 模型定义:
🤖 Claude Code:Subagent-3 开始执行 Task 3: 数据模型
规范合规审查:采用 SQLAlchemy 2.0 声明式风格(Mapped + mapped_column)
代码质量审查:password 字段不通过 API 暴露,时间字段自动管理
# app/model/user.py
from datetime import datetime
from sqlalchemy import String, DateTime, func
from sqlalchemy.orm import Mapped, mapped_column
from app.database import Base
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
username: Mapped[str] = mapped_column(
String(64), unique=True, nullable=False, index=True
)
password: Mapped[str] = mapped_column(String(128), nullable=False)
created_at: Mapped[datetime] = mapped_column(
DateTime, server_default=func.now()
)
updated_at: Mapped[datetime] = mapped_column(
DateTime, server_default=func.now(), onupdate=func.now()
)
SQLAlchemy 2.0 的声明式写法比旧版 Column() 更 Pythonic。Mapped[str] 提供类型提示,IDE 的自动补全体验极佳。通过 server_default=func.now() 让数据库管理默认值,比在 Python 端设置更可靠。
片段 2:Pydantic Schema(app/schema/user.py)
子 Agent 4 号执行 Task 4:
🤖 Claude Code:Subagent-4 开始执行 Task 4: Pydantic Schema
规范合规审查:请求与响应分别定义,密码字段不在响应中泄露
代码质量审查:加入 field 验证规则,约束 username 长度与格式
# app/schema/user.py
from pydantic import BaseModel, Field
class UserCreate(BaseModel):
username: str = Field(min_length=3, max_length=64, pattern=r"^[a-zA-Z0-9_]+$")
password: str = Field(min_length=6, max_length=128)
class UserLogin(BaseModel):
username: str
password: str
class UserResponse(BaseModel):
id: int
username: str
model_config = {"from_attributes": True}
Pydantic v2 的 Field() 远比 Go 的 binding tag 强大。pattern=r"^[a-zA-Z0-9_]+$" 直接在模型层做正则校验,FastAPI 会自动在 422 响应中返回详尽的验证错误信息。model_config = {"from_attributes": True} 等价于旧版的 orm_mode = True,允许直接从 SQLAlchemy 对象构造响应。
片段 3:Service 层(app/service/user.py)
子 Agent 6 号执行 Task 6,实现注册与登录的核心业务逻辑:
🤖 Claude Code:Subagent-6 开始执行 Task 6: Service 层
规范合规审查:密码使用 passlib bcrypt 哈希,JWT 签发后写入 Redis
代码质量审查:全部异步,Redis 写入具备降级逻辑
# app/service/user.py
import logging
from datetime import datetime, timedelta, timezone
import jwt
from passlib.context import CryptContext
from app.config import settings
from app.model.user import User
from app.repository.user import UserRepository
from app.schema.user import UserCreate
logger = logging.getLogger(__name__)
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
class UserService:
def __init__(self, repo: UserRepository, redis):
self.repo = repo
self.redis = redis
async def register(self, data: UserCreate) -> User:
"""注册:校验用户名唯一性,bcrypt 哈希密码,写入数据库"""
existing = await self.repo.get_by_username(data.username)
if existing:
raise ValueError("用户名已存在")
hashed = pwd_context.hash(data.password)
return await self.repo.create(data.username, hashed)
async def login(self, username: str, password: str) -> str:
"""登录:验证密码,签发 JWT,缓存至 Redis"""
user = await self.repo.get_by_username(username)
if not user:
raise ValueError("用户不存在")
if not pwd_context.verify(password, user.password):
raise ValueError("密码错误")
# 签发 JWT
payload = {
"user_id": user.id,
"username": user.username,
"exp": datetime.now(timezone.utc) + timedelta(hours=24),
}
token = jwt.encode(payload, settings.jwt_secret, algorithm="HS256")
# 缓存至 Redis,TTL 24 小时
try:
await self.redis.set(f"token:{user.id}", token, ex=86400)
except Exception as e:
# Redis 写入失败不影响登录
logger.warning("Redis 缓存 Token 失败: %s", e)
return token
与 Go 版本相似,Redis 写入失败被降级处理——登录流程不会因为缓存不可用而中断。passlib.CryptContext 是 Python 社区处理密码哈希的标准方案,支持 bcrypt、argon2 等算法,并自动处理算法版本迁移。
片段 4:认证依赖注入(app/middleware/auth.py)
子 Agent 7 号执行 Task 7,这是 Python 版本与 Go 版本差异最大的部分:
🤖 Claude Code:Subagent-7 开始执行 Task 7: 认证依赖
规范合规审查:使用 FastAPI Depends 注入,从 Authorization header 提取 Bearer Token
代码质量审查:HTTPException 统一错误格式,Redis 验证 Token 有效性
# app/middleware/auth.py
import logging
import jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from app.config import settings
from app.schema.user import UserResponse
logger = logging.getLogger(__name__)
security = HTTPBearer()
async def get_current_user(
credentials: HTTPAuthorizationCredentials = Depends(security),
) -> UserResponse:
"""从请求中提取并验证 JWT,返回当前用户"""
token = credentials.credentials
try:
payload = jwt.decode(token, settings.jwt_secret, algorithms=["HS256"])
except jwt.ExpiredSignatureError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token 已过期",
)
except jwt.InvalidTokenError:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token 无效",
)
user_id = payload.get("user_id")
username = payload.get("username")
if not user_id or not username:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Token 格式错误",
)
# 注意:完整版需要查询 Redis 验证 Token 是否仍在有效期内
# 这里在 Router 层通过 Redis 依赖完成
return UserResponse(id=user_id, username=username)
这正是 FastAPI 依赖注入的力量。
Go 版本需要手动编写 gin.HandlerFunc,自行解析 header、调用 c.Abort()、设置上下文。而 FastAPI 只需 Depends(get_current_user),框架自动完成以下步骤:
-
- 检查 Authorization header 是否存在
-
- 提取 Bearer Token
-
- 调用编写的验证函数
-
- 验证失败自动返回 401
-
- 验证通过自动将返回值注入路由函数参数
片段 5:启动入口(app/main.py)
子 Agent 9 号执行 Task 9:
🤖 Claude Code:Subagent-9 开始执行 Task 9: 启动入口
规范合规审查:通过 lifespan 管理 Redis 连接生命周期
代码质量审查:环境变量用 Pydantic Settings 加载,所有依赖以参数形式传递
# app/main.py
import logging
from contextlib import asynccontextmanager
import redis.asyncio as aioredis
from fastapi import FastAPI
from app.config import settings
from app.database import create_tables
from app.router.user import router as user_router
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
"""应用生命周期:启动时连接 Redis,关闭时释放"""
app.state.redis = aioredis.from_url(
f"redis://:{settings.redis_password}@{settings.redis_addr}/0",
decode_responses=True,
)
await create_tables()
logger.info("服务启动完成")
yield
await app.state.redis.close()
logger.info("服务关闭")
app = FastAPI(
title="FastAPI Server",
version="1.0.0",
lifespan=lifespan,
)
app.include_router(user_router, prefix="/api")
# app/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
db_url: str = "mysql+aiomysql://root:123456@127.0.0.1:3306/fastapi_api"
redis_addr: str = "localhost:6379"
redis_password: str = ""
jwt_secret: str = "my-secret-key"
port: int = 8000
model_config = {"env_file": ".env"}
settings = Settings()
FastAPI 的 lifespan 是 Python 版的“优雅启停”。使用 @asynccontextmanager 管理 Redis 连接的生命周期,比 Go 的 defer 更显式,也更贴合 Python 的上下文管理器习惯。
代码审查阶段
10 个 Task 全部执行完毕后,进入代码审查:
🤖 Claude Code:所有 10 个任务执行完毕。正在发起代码审查……
审查结果:
- • 规范合规:所有代码符合头脑风暴阶段确认的架构设计
- • 代码质量:全异步、依赖注入干净、Pydantic 校验完整
- • 潜在问题:
database.py中async_sessionmaker缺少expire_on_commit=False
AI 自动修复了 session 配置,确保异步查询不会在 commit 后触发懒加载。
验证与调试
启动验证
$ source venv/bin/activate
$ uvicorn app.main:app --reload
INFO: Uvicorn running on http://127.0.0.1:8000
INFO: Started reloader process
INFO: Application startup complete
FastAPI 自带的 Swagger UI 可通过 http://127.0.0.1:8000/docs 直接测试所有接口,这比 Go 版本需要额外安装 Swag 工具方便太多。
接口测试
测试 1:用户注册
$ curl -s -X POST http://localhost:8000/api/register \
-H "Content-Type: application/json" \
-d '{"username":"zhangsan","password":"abc123"}' | jq .
{
"id": 1,
"username": "zhangsan"
}
测试 2:用户登录
$ curl -s -X POST http://localhost:8000/api/login \
-H "Content-Type: application/json" \
-d '{"username":"zhangsan","password":"abc123"}' | jq .
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
测试 3:鉴权接口
$ TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
$ curl -s http://localhost:8000/api/echo \
-H "Authorization: Bearer $TOKEN" | jq .
{
"message": "认证成功",
"user_id": 1,
"username": "zhangsan"
}
三个接口均一次通过。
遇到的问题:Pydantic 验证 422
注册测试时,故意提交一个不合规的 username:
$ curl -s -X POST http://localhost:8000/api/register \
-H "Content-Type: application/json" \
-d '{"username":"ab","password":"123"}' | jq .
{
"detail": [
{
"type": "string_too_short",
"loc": ["body", "username"],
"msg": "String should have at least 3 characters",
"input": "ab"
},
{
"type": "string_too_short",
"loc": ["body", "password"],
"msg": "String should have at least 6 characters",
"input": "123"
}
]
}
FastAPI 自动返回 422 并附带详细的验证错误描述,而 Go 版本则需要手写 binding tag 和自定义错误处理才能达到同样效果。
遇到的问题:async session 未关闭
审查阶段发现 repository/user.py 的数据库 session 没有使用 async context manager:
🤖 Claude Code:发现 repository 层直接调用
async_session()但没有使用async with。在异步环境中,未关闭的 session 将导致连接池耗尽。
修复:
# 有问题的版本
async def get_by_username(self, username: str):
result = await self.db.execute(...) # session 可能泄漏
# 修复后
async def get_by_username(self, username: str):
async with AsyncSessionLocal() as session:
result = await session.execute(...)
return result.scalar_one_or_none()
这类是 Python 异步项目中的经典陷阱——Superpowers 的代码审查帮助我们提前发现并消除隐患。
最终成果
完整项目结构
python-api-server/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI 应用入口
│ ├── config.py # Pydantic Settings 配置
│ ├── database.py # SQLAlchemy 异步引擎
│ ├── deps.py # 公共依赖注入
│ ├── model/
│ │ ├── __init__.py
│ │ └── user.py # 用户 ORM 模型
│ ├── schema/
│ │ ├── __init__.py
│ │ └── user.py # Pydantic 请求/响应
│ ├── repository/
│ │ ├── __init__.py
│ │ └── user.py # 数据库操作
│ ├── service/
│ │ ├── __init__.py
│ │ └── user.py # 业务逻辑
│ ├── router/
│ │ ├── __init__.py
│ │ └── user.py # API 路由
│ └── middleware/
│ ├── __init__.py
│ └── auth.py # JWT 认证依赖
├── pyproject.toml # 项目配置 + 依赖
├── requirements.txt # pip 依赖
├── Dockerfile
├── docker-compose.yml
├── .env.example
└── README.md
四语言对比
| 指标 | Go | Spring Boot | Rust | Python |
|---|---|---|---|---|
| 文件数 | 14 | 22 | 21 | 15 |
| 代码行数 | ~400 | ~500 | ~450 | ~350 |
| 构建耗时 | 26 分钟 | 28 分钟 | 34 分钟 | 22 分钟 |
| Docker 镜像 | ~15 MB | ~200 MB | ~8 MB | ~50 MB |
| 冷启动 | ~50ms | ~3s | ~10ms | ~200ms |
| 自动文档 | 需 Swag | 需 SpringDoc | 需 utoipa | 内置 Swagger |
| 请求验证 | binding tag | @Valid | 手动验证 | Pydantic 内置 |
Python 版本代码量最少、构建最快,自动文档和请求验证均开箱即用。代价是 Docker 镜像比 Go/Rust 大,冷启动也比编译型语言慢。
Superpowers 七阶段映射
| 阶段 | 工作内容 | 耗时 |
|---|---|---|
| 1. Brainstorming | 5 轮问答确认架构设计 | 4 分钟 |
| 2. Git Worktree | 创建隔离工作区和新分支 | 1 分钟 |
| 3. Writing Plans | 生成 10 个 Task 的开发计划 | 2 分钟 |
| 4. Subagent Dev | 10 个子 Agent 顺序执行 | 8 分钟 |
| 5. Request Review | AI 自审代码规范和质量 | 2 分钟 |
| 6. Receive Review | 修复 session 泄漏等小问题 | 2 分钟 |
| 7. Finishing | 启动验证 + curl 测试 + bug 修复 | 3 分钟 |
总计约 22 分钟。Python 生态的动态类型让 AI 编码更快,Pydantic 的自动验证也减少了手写校验代码的工作量。
进阶技巧
FastAPI 依赖注入的魔法
FastAPI 的 Depends() 是本文最值得深入理解的核心特性。它与 Go 的中间件模式有本质区别:
# Go 写法:中间件手动处理一切
func AuthMiddleware(rdb *redis.Client, jwtSecret string) gin.HandlerFunc {
return func(c *gin.Context) {
// 手动取 header
// 手动解析 JWT
// 手动设置上下文
// 手动调用 c.Next()
}
}
# FastAPI 写法:声明式依赖
@router.get("/echo")
async def echo(user: UserResponse = Depends(get_current_user)):
# user 已经是验证后的对象,直接用
return {"message": "认证成功", "user_id": user.id}
Depends() 让你只写验证逻辑,不写胶水代码。框架负责参数提取、错误处理、响应格式化。
Pydantic Settings 的威力
config.py 使用了 pydantic-settings,它比 Go 的 os.Getenv 强在哪里?
# 自动类型转换 + 环境变量加载 + .env 文件支持
class Settings(BaseSettings):
db_url: str = "mysql+aiomysql://root:123456@localhost/db"
redis_addr: str = "localhost:6379"
port: int = 8000 # 自动转 int,无需 strconv.Atoi
model_config = {"env_file": ".env"}
不需要手写 getEnv() 加默认值处理。修改配置只需改动 .env 文件,代码零修改。
在 CLAUDE.md 中预设 Python 项目规范
## Python 项目规范
- 使用 FastAPI + SQLAlchemy 2.0 异步栈
- 所有 IO 操作使用 async/await
- 请求验证用 Pydantic v2,不手动校验
- 依赖注入用 Depends(),不用全局变量
- 代码格式化用 ruff,不用 black + isort
常见问题
Q1:FastAPI 性能是否足以用于生产?
FastAPI 在 TechEmpower 基准测试中,单机 QPS 可达到 3 万以上(JSON 响应),与 Go 的 Gin(4–5 万)处于同一量级。对于绝大多数 API 服务,这个性能完全足够。Instagram、Notion、Microsoft Teams 都在生产环境中运行 FastAPI。
Q2:为什么不用 asyncpg + PostgreSQL?
本文选用 MySQL 是为了与 Go、Spring Boot、Rust 各版本保持一致,便于四语言横向比较。实际上 FastAPI + asyncpg + PostgreSQL 是很多团队的首选组合,替换只需要更换数据库连接串。
Q3:Python 3.12 有哪些新特性会影响开发?
3.12 的类型语法改进(如 type X = Y)、持续的 CPython 性能提升,以及更清晰的错误提示,都让开发体验更好。建议所有新项目直接使用 3.12+。
Q4:与 Go 版本相比,应该选哪一个?
- • 团队有 Python 经验 + AI/ML 需求 → Python
- • 追求极致性能 + 微服务架构 → Go
- • 两者都需要 → 参考 Kubernetes 的做法:控制面用 Go,数据面按需选择
延伸阅读
- • 本系列第 21 篇《Go API Server 脚手架》——对比 Go 版本的 Superpowers 实战
- • 本系列第 16 篇《Superpowers 工作流》——七阶段工作流完整理论
- • FastAPI 官方文档[1]
- • SQLAlchemy 2.0 文档[2]
- • Pydantic v2 文档[3]
四语言脚手架即将开源
本系列已经完成四语言 API Server 脚手架:
| 语言 | 框架 | 文章 |
|---|---|---|
| Go | Gin + GORM | 第 21 篇 |
| Java | Spring Boot + MyBatis-Plus | 第 22 篇 |
| Rust | Axum + SQLx | 第 23 篇 |
| Python | FastAPI + SQLAlchemy | 本文 |
四个项目的完整源码即将在 GitHub 开源,包含:
- • 完整的注册 / 登录 / JWT 鉴权实现
- • Docker Compose 一键部署(MySQL + Redis + API)
- • 统一的 API 接口设计,方便横向对比
- • 生产级的项目结构和代码规范
无论你使用哪种语言,Superpowers 工作流都是一致的——Brainstorming → Worktree → Plans → Subagent → Review → Fix → Verify。框架会变,工程纪律不变。
引用链接
[1] FastAPI 官方文档: https://fastapi.tiangolo.com/
[2] SQLAlchemy 2.0 文档: https://docs.sqlalchemy.org/en/20/
[3] Pydantic v2 文档: https://docs.pydantic.dev/