FastAPI初体验:为什么它成了Python Web开发的新宠?
在Web框架百花齐放的今天,FastAPI凭借什么在短短几年内迅速崛起?让我们一起探索这个「现代Python Web开发的新选择」。
1. 现代Web开发的新选择
还记得几年前我还在用Flask写API的时候,每次都要手动写文档、配置验证、处理异步请求... 直到2018年FastAPI横空出世,一切都变得不一样了。
FastAPI是什么?
- 一个现代、快速(高性能)的Web框架,用于构建API
- 基于标准Python类型提示
- 自动生成交互式API文档
- 支持异步编程(async/await)
- 由Sebastián Ramírez(tiangolo)创建并维护
python
# 感受一下FastAPI的简洁
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.get("/")
async def read_root():
return {"Hello": "World"}
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}2. FastAPI vs Flask vs Django:三大框架终极对比
性能基准测试
根据TechEmpower的基准测试,FastAPI在性能上明显优于传统同步框架:
| 框架 | 请求/秒(JSON序列化) | 类型提示 | 异步支持 | 学习曲线 |
|---|---|---|---|---|
| FastAPI | 约100,000 | ✅ 内置 | ✅ 原生 | 中等 |
| Flask | 约20,000 | ❌ 需要扩展 | ❌ 需扩展 | 简单 |
| Django | 约15,000 | ❌ 需要扩展 | ✅ 3.1+ | 陡峭 |
开发体验对比
Flask - "微框架"的灵活
python
# Flask示例
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/items/<int:item_id>', methods=['PUT'])
def update_item(item_id):
data = request.get_json()
# 需要手动验证数据
if not data or 'name' not in data:
return jsonify({'error': 'Bad request'}), 400
return jsonify({'item_id': item_id, 'name': data['name']})Django - "全功能"的重量级
python
# Django REST Framework示例
from rest_framework import serializers, viewsets
class ItemSerializer(serializers.Serializer):
name = serializers.CharField(max_length=100)
price = serializers.FloatField()
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
# 需要大量配置和样板代码FastAPI - "现代"的平衡
python
# FastAPI示例 - 简洁且功能强大
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI()
class Item(BaseModel):
name: str = Field(..., min_length=1, max_length=100)
price: float = Field(..., gt=0)
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
# 自动数据验证、序列化、文档生成
return {"item_id": item_id, **item.dict()}3. 安装与环境配置一步到位
环境准备
bash
# 1. 创建虚拟环境(推荐使用Python 3.7+)
python -m venv venv
# Windows激活
venv\Scripts\activate
# Linux/Mac激活
source venv/bin/activate
# 2. 安装FastAPI和服务器
pip install "fastapi[all]" # 包含所有依赖
# 或者分步安装
pip install fastapi
pip install uvicorn[standard] # ASGI服务器
pip install pydantic # 数据验证
pip install python-multipart # 表单支持开发工具推荐
bash
# 代码格式化
pip install black isort
# 代码检查
pip install flake8 mypy
# 自动重载开发
pip install watchfiles
# 环境管理(可选)
pip install python-dotenv最小项目结构
my_fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py # 应用入口
│ ├── dependencies.py # 依赖项
│ ├── routers/ # 路由模块
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ ├── models/ # Pydantic模型
│ │ └── schemas.py
│ └── config.py # 配置
├── tests/ # 测试文件
├── requirements.txt # 依赖列表
└── .env.example # 环境变量示例4. 你的第一个API:5分钟上手
完整示例:待办事项API
python
# main.py
from typing import List, Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from datetime import datetime
app = FastAPI(
title="Todo API",
description="一个简单的待办事项API示例",
version="1.0.0"
)
# 数据模型
class TodoCreate(BaseModel):
title: str
description: Optional[str] = None
completed: bool = False
class Todo(TodoCreate):
id: int
created_at: datetime
updated_at: datetime
# 内存数据库(示例)
todos_db = []
current_id = 0
@app.get("/")
async def root():
"""API根端点"""
return {
"message": "欢迎使用Todo API",
"docs": "/docs",
"redoc": "/redoc"
}
@app.get("/todos", response_model=List[Todo])
async def list_todos(completed: Optional[bool] = None):
"""获取待办事项列表"""
if completed is None:
return todos_db
return [todo for todo in todos_db if todo["completed"] == completed]
@app.get("/todos/{todo_id}", response_model=Todo)
async def get_todo(todo_id: int):
"""根据ID获取单个待办事项"""
for todo in todos_db:
if todo["id"] == todo_id:
return todo
raise HTTPException(status_code=404, detail="Todo not found")
@app.post("/todos", response_model=Todo, status_code=201)
async def create_todo(todo: TodoCreate):
"""创建新的待办事项"""
global current_id
current_id += 1
now = datetime.now()
new_todo = {
"id": current_id,
**todo.dict(),
"created_at": now,
"updated_at": now
}
todos_db.append(new_todo)
return new_todo
@app.put("/todos/{todo_id}", response_model=Todo)
async def update_todo(todo_id: int, todo_update: TodoCreate):
"""更新待办事项"""
for index, todo in enumerate(todos_db):
if todo["id"] == todo_id:
updated_todo = {
**todo,
**todo_update.dict(exclude_unset=True),
"updated_at": datetime.now()
}
todos_db[index] = updated_todo
return updated_todo
raise HTTPException(status_code=404, detail="Todo not found")
@app.delete("/todos/{todo_id}", status_code=204)
async def delete_todo(todo_id: int):
"""删除待办事项"""
for index, todo in enumerate(todos_db):
if todo["id"] == todo_id:
todos_db.pop(index)
return
raise HTTPException(status_code=404, detail="Todo not found")运行你的API
bash
# 开发模式运行(带热重载)
uvicorn main:app --reload --host 0.0.0.0 --port 8000
# 访问你的API
# http://localhost:80005. 自动交互文档:Swagger UI初探
FastAPI最酷的功能之一就是自动生成交互式API文档。启动应用后,访问:
- Swagger UI文档:
http://localhost:8000/docs - ReDoc文档:
http://localhost:8000/redoc
自定义文档配置
python
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="我的API文档",
version="2.0.0",
description="这是我的自定义API文档",
routes=app.routes,
)
# 自定义文档内容
openapi_schema["info"]["x-logo"] = {
"url": "https://fastapi.tiangolo.com/img/logo-margin/logo-teal.png"
}
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
# API端点标签和描述
@app.post("/items/",
tags=["items"],
summary="创建项目",
description="创建一个新的项目并保存到数据库",
response_description="创建成功的项目详情")
async def create_item(item: Item):
return item6. 性能优势:异步编程的威力
同步 vs 异步对比
python
import asyncio
import time
from fastapi import FastAPI
import httpx
app = FastAPI()
# 1. 同步版本(阻塞)
@app.get("/sync")
def sync_endpoint():
"""同步端点 - 每个请求都会阻塞"""
time.sleep(1) # 模拟I/O操作
return {"message": "同步响应"}
# 2. 异步版本(非阻塞)
@app.get("/async")
async def async_endpoint():
"""异步端点 - 非阻塞,可同时处理多个请求"""
await asyncio.sleep(1) # 异步等待
return {"message": "异步响应"}
# 3. 异步HTTP请求示例
@app.get("/github/{username}")
async def get_github_user(username: str):
"""异步获取GitHub用户信息"""
async with httpx.AsyncClient() as client:
# 非阻塞的HTTP请求
response = await client.get(
f"https://api.github.com/users/{username}"
)
if response.status_code == 200:
return response.json()
return {"error": "用户未找到"}性能测试
python
# 使用async/await进行并发处理
from typing import List
import asyncio
@app.get("/concurrent")
async def concurrent_requests():
"""并发执行多个异步任务"""
tasks = [
fetch_data_from_db(i) for i in range(10)
]
results = await asyncio.gather(*tasks)
return {"results": results}
async def fetch_data_from_db(item_id: int):
"""模拟数据库查询"""
await asyncio.sleep(0.5) # 模拟I/O等待
return {"id": item_id, "data": f"Item {item_id}"}7. 项目结构最佳实践入门
模块化项目结构
fastapi_project/
├── app/
│ ├── api/ # API端点
│ │ ├── v1/ # API版本1
│ │ │ ├── endpoints/
│ │ │ │ ├── items.py
│ │ │ │ ├── users.py
│ │ │ │ └── auth.py
│ │ │ └── api_v1.py # v1路由聚合
│ │ └── deps.py # 依赖项
│ ├── core/ # 核心配置
│ │ ├── config.py # 配置管理
│ │ ├── security.py # 安全相关
│ │ └── events.py # 启动/关闭事件
│ ├── models/ # 数据模型
│ │ ├── domain/ # 领域模型
│ │ ├── schemas.py # Pydantic模型
│ │ └── enums.py # 枚举类型
│ ├── services/ # 业务逻辑
│ │ ├── item_service.py
│ │ └── user_service.py
│ ├── db/ # 数据库相关
│ │ ├── session.py # 数据库会话
│ │ └── repositories/ # 数据访问层
│ ├── utils/ # 工具函数
│ └── main.py # 应用入口
├── tests/ # 测试
├── alembic/ # 数据库迁移
├── docker-compose.yml
├── Dockerfile
└── requirements/
├── base.txt
├── dev.txt
└── prod.txt配置管理示例
python
# app/core/config.py
from pydantic import BaseSettings
from typing import Optional
class Settings(BaseSettings):
"""应用配置"""
APP_NAME: str = "FastAPI项目"
DEBUG: bool = False
# 数据库配置
DATABASE_URL: str = "sqlite:///./test.db"
# JWT配置
SECRET_KEY: str
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# CORS配置
BACKEND_CORS_ORIGINS: list = ["http://localhost:3000"]
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()应用工厂模式
python
# app/main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.api.v1.api import api_router
from app.core.config import settings
from app.core.events import create_start_app_handler
def create_application() -> FastAPI:
"""应用工厂函数"""
application = FastAPI(
title=settings.APP_NAME,
openapi_url=f"{settings.API_V1_STR}/openapi.json"
)
# 配置CORS
if settings.BACKEND_CORS_ORIGINS:
application.add_middleware(
CORSMiddleware,
allow_origins=settings.BACKEND_CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 注册路由
application.include_router(
api_router,
prefix=settings.API_V1_STR
)
# 添加启动/关闭事件
application.add_event_handler(
"startup",
create_start_app_handler(application)
)
return application
app = create_application()总结
FastAPI之所以能迅速赢得开发者青睐,主要归功于:
- 极致的开发体验 - 类型提示、自动文档、数据验证
- 卓越的性能 - 基于Starlette和Pydantic,支持异步
- 简洁的语法 - Pythonic的设计,学习曲线平缓
- 强大的生态系统 - 与SQLAlchemy、Pydantic等完美集成
下一步学习建议
- 官方文档:FastAPI官方文档 - 最全面、最新的资料
- 实践项目:从简单的CRUD API开始,逐步增加功能
- 社区资源:
- 深入阅读:
- 《FastAPI Web开发入门、进阶与实战》
- 《Building Data Science Applications with FastAPI》
FastAPI不仅是一个框架,更是Python现代Web开发的典范。无论你是初学者还是经验丰富的开发者,FastAPI都能为你带来前所未有的开发体验。
记住:最好的学习方式就是动手实践! 现在就去创建你的第一个FastAPI项目吧!
欢迎在评论区分享你的FastAPI使用体验! 有任何问题或建议,我都会认真阅读并回复。