跳到正文
为什么这次写接口我选 FastAPI,不是 Flask
为什么这次写接口我选 FastAPI,不是 Flask

为什么这次写接口我选 FastAPI,不是 Flask

Web 框架一搜一大把。Flask 我写过小工具,Django 用 DRF 做过完整 REST API,这次却选了 FastAPI。这篇不讲怎么用,讲我为什么在这个节点选它、它和 Flask 的取舍差在哪。

速读#

这篇不是 FastAPI 教程,而是解释为什么在“快速写规整接口”这个阶段,我选 FastAPI 而不是 Flask。核心判断是自由和定型的取舍:Flask 给自由,FastAPI 用类型注解把接口定义、参数校验和自动文档提前固定下来。

打动我的点:一份注解管三处#

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

启动后打开 /docs,Swagger UI 自动生成能直接点按钮测的交互文档。第一次见,真心惊艳。

靠的是 FastAPI 对类型注解的运行时解释:item_id: int 既声明处理函数需要整数,又驱动请求转换与校验(非数字默认返回 422),还进入 OpenAPI 参数类型。Python 解释器本身不会因为注解自动校验 HTTP 输入,是 FastAPI 与 Pydantic 在框架边界上完成了这件事。一份声明,函数签名、校验和文档三处复用。

请求体是同一套逻辑,换成 Pydantic 模型:

from pydantic import BaseModel, Field
class ItemCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)
price: float = Field(gt=0, allow_inf_nan=False)
class ItemOut(ItemCreate):
id: int
@app.post("/items", response_model=ItemOut, status_code=201)
def create_item(item: ItemCreate):
return ItemOut(id=1, **item.model_dump())

字段缺失、长度不符或价格非法时,请求默认在进入函数前以 422 拒绝,并指出字段位置。response_model 同时验证和过滤输出,避免函数偶然多返回内部字段;若服务端返回值不满足模型,那是服务端错误,通常会变成 500,而不是把责任推给客户端。这里的 id=1 只是演示接口形状,真正实现应由数据库生成。

文档也不止 Swagger UI:/redoc 是另一份阅读视图,背后都来自 /openapi.json。客户端可以据此生成代码,但生成质量取决于 operation ID、响应模型、错误响应和鉴权声明是否完整。路径、参数、类型与必填项会随代码更新,业务语义、示例、权限和失败条件仍可能过期。自动文档减少重复,不消灭文档维护。

开发环境默认开放 /docs/redoc 和 OpenAPI 很方便;生产是否公开取决于 API 是否面向外部。关闭或加认证只能减少信息暴露,不能代替每个业务接口自己的认证与授权。

FastAPI vs Flask#

FlaskFastAPI
核心取向小而可扩展,能力按需组合围绕类型模型集成校验、DI 与 OpenAPI
校验 / 文档核心较少,按项目选择扩展或上层框架请求模型与 OpenAPI 默认联动
我何时选已有 Flask 生态或需要极小核心想快速建立类型化 HTTP 契约

Flask 核心小,意味着项目要自行选择校验、序列化和 OpenAPI 的组合;APIFlask、flask-smorest 等方案也能把这些能力集成起来,并不必然是三套散件。FastAPI 的优势是默认把这条路径接好,少做选型和胶水代码;代价是要接受 Pydantic、依赖注入和 ASGI 这套模型。单一模型能减少形状重复,契约是否可靠仍取决于测试和兼容策略。

定型也有代价,但“字段变化要改模型”通常正是契约应该显式发生的变化。真正适合透传任意 JSON、极简 webhook 或已有 WSGI 扩展体系的场景,Flask 的小核心会更直接;需要大量结构化接口时,FastAPI 的默认集成更省事。场景在回答“愿意维护哪些约束”,不是框架在比高下。

顺带交代一句:FastAPI 常被拿来说 async 性能,但那不是我这个节点的理由。普通 def 路由会在线程池运行,async def 只有在内部 I/O 库也是异步并正确 await 时才避免阻塞事件循环;CPU 密集工作仍应放到其他进程或任务系统。我的量级离“瓶颈在框架”很远,为不存在的流量挑性能,等于把选型理由让给宣传页。

没有绝对更好。问自己:这个场景要的是自由,还是定型?答案不同,选的就不同。

小取舍#

Terminal window
python -m pip install "fastapi[standard]"
# 开发
fastapi dev main.py
# 生产入口:不启用 reload,进程数量与托管方式按部署环境决定
fastapi run main.py
场景选择
本地快速开始[standard] 一次带上 CLI、Uvicorn 及常用可选依赖
最小部署只安装实际使用的依赖并锁版本,不把 extras 当稳定性开关
生产运行关闭 reload,配置反向代理或平台入口、健康检查、日志和进程重启

[standard] 是便利集合,不是“生产版 FastAPI”;未使用的模板、表单等依赖没有必要为了仪式全部带上。单机可以由进程管理器托管 Uvicorn,多副本容器通常每个容器一个进程再由平台扩缩;不要同时堆多 worker 和多副本却从未测过资源上限。

第一个接口从零跑到浏览器里看到自己的 JSON,反馈感很强。但这篇真正想留的是取舍框架:

选框架先问:我这个场景要的是自由还是定型。

版权许可

CC BY-NC-SA 4.0 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

相关文章

s1oopX

登录 s1oopX