1208 字
约 4 分钟
7
S10-J02 · Flask ↔ FastAPI:迁移与对照

适用读者:要在两个框架之间做迁移/共存决策的人。
前置:S10-B04、S10-B05。
实测环境:FastAPI 0.162.0 / Flask 3.1.3 / Python 3.12.3(两框架对同一请求的差异为实测)。
覆盖旧文:—(E 驱动)
覆盖扩展:E-S10-011(同步 vs 异步 handler)、E-S10-012(校验位置差异)。
上一篇:S10-J01 · 依赖治理:requirements / environment.yml / 锁版本
下一篇:S10-A01 · Web 框架选型 ADR。


1. 一句话结论

迁移的难点不在语法,在"错误语义"和"校验位置"两件事——它们会直接影响前端与调用方。

维度 Flask FastAPI 迁移要改什么
参数校验 手写 / 第三方 框架层(Pydantic) 把 if not x: return 400 删掉,改类型标注
错误响应 自定义 JSON 422 detail 数组 前端要能解析两种结构
文档 扩展 内建 可直接删掉手写文档
异步 有限 原生 handler 是否 async def 要逐个判断
依赖注入 手动 Depends 可收敛"获取 db/session"的样板

2. 同一接口的两种写法

2.1 Flask

@app.route("/items/<int:item_id>")
def item(item_id):
    if item_id > 100:
        abort(404)
    return jsonify(id=item_id, name="apple")

2.2 FastAPI

@app.get("/items/{item_id}")
def get_item(item_id: int):
    if item_id not in DB:
        raise HTTPException(status_code=404, detail="item not found")
    return {"id": item_id, **DB[item_id].model_dump()}

代码量接近,但"校验"的归属完全不同:Flask 里你必须自己判断 item_id 是否合法;FastAPI 在进入函数前已经校验完。


3. 实测:错误语义差异(迁移时最容易翻车)

请求 Flask 3.1.3 FastAPI 0.162.0
/items/abc 404 422
/items/999(不存在) 404(业务 abort) 404(HTTPException)
请求体字段非法 手写决定(常见 400) 422 + 逐字段明细

为什么这条必须写进迁移清单:

客户端预期 Flask 行为 FastAPI 行为
"接口不存在" 看到 404 ✅ 看到 422(需先看 detail)
"参数传错" 看到 404 ❌(误判为接口没了) 看到 422 ✅

迁移动作:前端/SDK 需要同时兼容两种错误结构,或服务端加一层"统一错误包装"(把 422 转成业务错误码)。


4. 迁移清单(可执行)

# 项 动作
1 路由 @app.route(..., methods=["POST"]) → @app.post(...)
2 参数 手写校验 → 类型标注 + Pydantic 模型
3 错误 abort/jsonify → HTTPException + 自定义 exception_handler
4 依赖 手动获取 → Depends(db、鉴权、分页)
5 异步 逐个判断:有阻塞 IO 的 handler 改 async 或丢线程池
6 文档 删手写 Swagger 配置,使用 /docs
7 测试 断言状态码的地方要改(404 → 422)
8 部署 flask run → uvicorn(或 gunicorn + uvicorn worker)

5. 异步这件事(E-S10-011)

写法 行为
def handler()(同步) FastAPI 放线程池执行;阻塞调用会占线程
async def handler() 事件循环执行;内部若有阻塞调用会卡住整个循环

判据:

handler 里有没有阻塞调用(同步 DB 驱动、requests、文件 IO)?
├── 有,且用同步库 → 用 def(交给线程池)
└── 有,但已换成异步库(asyncpg/httpx) → 用 async def

最常见的错误:async def 里调 requests.get() —— 单请求看起来没事,并发一上来整个服务卡死。


6. 五个误区

误区 真相
"FastAPI 一定更快" 高并发+异步 IO 才明显;纯计算型差别不大
"迁移就是改装饰器" 校验/错误/测试/部署都要改
"async def 越多越好" 阻塞调用放进 async 会拖垮事件循环
"Flask 不能异步" 3.x 支持,但生态多为同步
"错误码可以最后再调" 前端会先炸;状态码语义要在迁移前定

7. 自检

  1. /items/abc 在两框架下的状态码分别是什么?为什么?
  2. 迁移清单里哪一项最容易漏?
  3. async def 里调同步 requests 会发生什么?
  4. 为什么建议加"统一错误包装层"?
  5. 什么情况下迁移反而不划算?

8. 下一篇

S10-A01 · Web 框架选型 ADR(FastAPI / Flask / Django)

对照完之后,进入架构决策:按什么维度选、被否方案怎么留证据、以及"什么时候该选 Django"。


本篇属于系列《S10 · Python 语言与环境》。扩展点 E-S10-011/012。两框架错误语义差异为 2026-11-05 实测。

S10-J02 · Flask ↔ FastAPI:迁移与对照
https://www.clxhxhhr.top/posts/5322/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。