Skip to content

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:8000

5. 自动交互文档:Swagger UI初探

FastAPI最酷的功能之一就是自动生成交互式API文档。启动应用后,访问:

  1. Swagger UI文档http://localhost:8000/docs
  2. 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 item

6. 性能优势:异步编程的威力

同步 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之所以能迅速赢得开发者青睐,主要归功于:

  1. 极致的开发体验 - 类型提示、自动文档、数据验证
  2. 卓越的性能 - 基于Starlette和Pydantic,支持异步
  3. 简洁的语法 - Pythonic的设计,学习曲线平缓
  4. 强大的生态系统 - 与SQLAlchemy、Pydantic等完美集成

下一步学习建议

  1. 官方文档FastAPI官方文档 - 最全面、最新的资料
  2. 实践项目:从简单的CRUD API开始,逐步增加功能
  3. 社区资源
  4. 深入阅读
    • 《FastAPI Web开发入门、进阶与实战》
    • 《Building Data Science Applications with FastAPI》

FastAPI不仅是一个框架,更是Python现代Web开发的典范。无论你是初学者还是经验丰富的开发者,FastAPI都能为你带来前所未有的开发体验。

记住:最好的学习方式就是动手实践! 现在就去创建你的第一个FastAPI项目吧!


欢迎在评论区分享你的FastAPI使用体验! 有任何问题或建议,我都会认真阅读并回复。

热爱生活,喜好美食,追求未来!