摘要:Python做Web API,Flask和FastAPI是最主流的两个选择。本文用同一个需求分别实现,从性能、开发体验、生态等维度做对比,帮你做出正确的技术选型。
需求:一个简单的待办事项API
实现增删改查四个接口:
GET /todos— 获取所有待办POST /todos— 创建待办PUT /todos/{id}— 更新待办DELETE /todos/{id}— 删除待办
Flask实现
pip install flask
from flask import Flask, request, jsonify
app = Flask(__name__)
# 内存存储(生产环境用数据库)
todos = {}
next_id = 1
@app.route('/todos', methods=['GET'])
def get_todos():
return jsonify(list(todos.values()))
@app.route('/todos', methods=['POST'])
def create_todo():
global next_id
data = request.get_json()
if not data or 'title' not in data:
return jsonify({'error': '缺少title字段'}), 400
todo = {
'id': next_id,
'title': data['title'],
'done': False,
}
todos[next_id] = todo
next_id += 1
return jsonify(todo), 201
@app.route('/todos/<int:todo_id>', methods=['PUT'])
def update_todo(todo_id):
if todo_id not in todos:
return jsonify({'error': '未找到'}), 404
data = request.get_json()
todo = todos[todo_id]
todo['title'] = data.get('title', todo['title'])
todo['done'] = data.get('done', todo['done'])
return jsonify(todo)
@app.route('/todos/<int:todo_id>', methods=['DELETE'])
def delete_todo(todo_id):
if todo_id not in todos:
return jsonify({'error': '未找到'}), 404
del todos[todo_id]
return '', 204
if __name__ == '__main__':
app.run(debug=True, port=8000)
FastAPI实现
pip install fastapi uvicorn
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional
app = FastAPI(title='待办事项API', version='1.0')
todos = {}
next_id = 1
class TodoCreate(BaseModel):
title: str
class TodoUpdate(BaseModel):
title: Optional[str] = None
done: Optional[bool] = None
class TodoResponse(BaseModel):
id: int
title: str
done: bool
@app.get('/todos', response_model=list[TodoResponse])
def get_todos():
return list(todos.values())
@app.post('/todos', response_model=TodoResponse, status_code=201)
def create_todo(data: TodoCreate):
global next_id
todo = {'id': next_id, 'title': data.title, 'done': False}
todos[next_id] = todo
next_id += 1
return todo
@app.put('/todos/{todo_id}', response_model=TodoResponse)
def update_todo(todo_id: int, data: TodoUpdate):
if todo_id not in todos:
raise HTTPException(status_code=404, detail='未找到')
todo = todos[todo_id]
if data.title is not None:
todo['title'] = data.title
if data.done is not None:
todo['done'] = data.done
return todo
@app.delete('/todos/{todo_id}', status_code=204)
def delete_todo(todo_id: int):
if todo_id not in todos:
raise HTTPException(status_code=404, detail='未找到')
del todos[todo_id]
# 运行:uvicorn main:app --reload --port 8000
对比分析
1. 参数校验
Flask需要手动校验每个参数:
# Flask:手动校验
data = request.get_json()
if not data or 'title' not in data:
return jsonify({'error': '缺少title'}), 400
if not isinstance(data['title'], str):
return jsonify({'error': 'title必须是字符串'}), 400
FastAPI用Pydantic模型自动校验:
# FastAPI:声明即校验
class TodoCreate(BaseModel):
title: str # 自动校验类型,缺失时返回422错误
FastAPI在这方面完胜,代码量少一半,错误信息还更友好。
2. API文档
Flask需要额外安装flask-swagger或flasgger:
pip install flasgger
FastAPI自带交互式文档,启动后访问 /docs(Swagger UI)或 /redoc(ReDoc),零配置。
3. 异步支持
Flask 2.0+支持async,但底层仍是WSGI:
# Flask:async支持有限
@app.route('/data')
async def get_data():
data = await fetch_from_db() # 可以用,但性能提升有限
return jsonify(data)
FastAPI原生异步,基于ASGI:
# FastAPI:原生异步
@app.get('/data')
async def get_data():
data = await fetch_from_db() # 真正的异步,性能拉满
return data
4. 性能基准
用wrk做简单压测(GET /todos,100并发):
| 框架 | 请求/秒 | 平均延迟 |
|---|---|---|
| Flask + gunicorn | ~2,800 | 35ms |
| FastAPI + uvicorn | ~8,500 | 12ms |
FastAPI快约3倍,主要得益于ASGI和Starlette底层。
5. 生态和社区
| 维度 | Flask | FastAPI |
|---|---|---|
| 发布年份 | 2010 | 2018 |
| GitHub Stars | 68k+ | 78k+ |
| 第三方扩展 | 极其丰富 | 快速增长 |
| 学习资料 | 海量 | 丰富 |
| 企业采用 | 广泛 | 快速增长 |
Flask生态更成熟,几乎任何需求都能找到现成的扩展。FastAPI虽然年轻,但增长势头很猛。
怎么选?
选Flask的场景:
- 团队熟悉Flask,迁移成本高
- 需要大量Flask扩展(如Flask-Admin、Flask-Login)
- 简单的内部工具或原型
- 需要服务端渲染(Jinja2模板)
选FastAPI的场景:
- 新项目,没有历史包袱
- 纯API服务(前后端分离)
- 需要高性能和异步
- 重视类型安全和自动文档
- 微服务架构
我的建议
2026年了,新项目直接上FastAPI。它在开发体验和性能上都有明显优势,生态也已经足够成熟。Flask依然是好框架,但FastAPI代表了Python Web开发的未来方向。
如果你的项目需要服务端渲染,考虑Flask或Django。纯API服务,FastAPI是当前最优解。