FastAPI:基于 Starlette 与 Pydantic 构建高性能 API

好嘞!各位亲爱的代码艺术家们,今天咱们不谈风花雪月,就来聊聊这个火遍全球的API界新宠——FastAPI!🚀

FastAPI:API界的法拉利,快到你怀疑人生!

想象一下,你是一位顶级的厨师👨‍🍳,每天要接待来自世界各地的食客。他们对食物的要求五花八门,有的要低脂,有的要无麸质,有的甚至要指定食材的产地和年份!如果让你手写菜单,并针对每个顾客的需求定制菜谱,那简直是噩梦!

而FastAPI,就是你厨房里的智能菜谱生成器!它能根据顾客(前端开发者)的需求,自动生成API接口,而且速度快如闪电,安全可靠,让你有更多时间去专研厨艺(写更棒的代码)。

一、 为什么选择FastAPI?难道它真的比别人优秀吗?

在API开发的世界里,选择框架就像选对象,颜值、身材、性格、家世,一个都不能少!FastAPI之所以能脱颖而出,靠的可不是炒作,而是硬实力!

特性 FastAPI Flask Django REST Framework
性能 非常高 (基于 Starlette 和 Pydantic) 相对较低 较高 (但通常需要更多配置)
自动文档 内置 Swagger UI 和 ReDoc 需要额外的库 (如 Flask-RESTful, Flask-API) 需要额外的库 (如 coreapi, drf-yasg)
数据校验 内置 Pydantic 数据验证 需要额外的库 (如 Marshmallow) 内置序列化器,但验证不如 Pydantic 灵活
异步支持 原生支持 async/await 需要 Flask 的异步扩展 需要额外的库或复杂配置才能实现完全异步支持
易用性 非常简单,学习曲线短 相对简单 学习曲线较长
适用场景 需要高性能、快速开发的 API 应用 小型 API,简单 Web 应用 大型 API,复杂业务逻辑
社区活跃度 非常活跃 活跃 活跃

简单来说,FastAPI的优势可以总结为以下几点:

  1. 速度快到飞起 🚀: 基于 Starlette 和 Pydantic 构建,性能比肩 NodeJS 和 Go,让你的API像猎豹一样迅猛!
  2. 代码量少到哭泣 😭: 强大的数据验证和自动文档生成功能,让你告别繁琐的重复劳动,把更多精力放在核心业务逻辑上。
  3. 颜值高到窒息 😍: 自动生成的 Swagger UI 和 ReDoc 文档,让你的API拥有堪比米其林餐厅的精致摆盘。
  4. 智能到尖叫 🤯: Pydantic 的数据验证功能,不仅能保证数据的准确性,还能提供详细的错误提示,让你的代码更加健壮。
  5. 拥抱异步编程 😴: 原生支持 async/await,轻松处理高并发请求,让你的API在面对海量用户时也能游刃有余。

二、 快速上手:用 FastAPI 搭建你的第一个 API

光说不练假把式,咱们来撸起袖子,用 FastAPI 搭建一个简单的 API,感受一下它的魅力。

1. 安装 FastAPI 和 Uvicorn

pip install fastapi uvicorn
  • fastapi: FastAPI 框架本身。
  • uvicorn: 一个 ASGI 服务器,用于运行你的 FastAPI 应用。

2. 创建 main.py 文件

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    description: str | None = None  # Optional field
    price: float
    tax: float | None = None

@app.get("/")
async def read_root():
    return {"Hello": "World"}

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

@app.post("/items/")
async def create_item(item: Item):
    item_dict = item.model_dump()
    if item.tax:
        price_with_tax = item.price + item.tax
        item_dict.update({"price_with_tax": price_with_tax})
    return item_dict

代码解读:

  • from fastapi import FastAPI: 导入 FastAPI 类。
  • app = FastAPI(): 创建 FastAPI 应用实例。
  • @app.get("/"): 定义一个 GET 请求的路由,路径为根目录 /
  • async def read_root(): 定义一个异步函数,用于处理 GET 请求,返回一个 JSON 对象。
  • @app.get("/items/{item_id}"): 定义一个 GET 请求的路由,路径为 /items/{item_id},其中 item_id 是一个路径参数。
  • async def read_item(item_id: int, q: str | None = None): 定义一个异步函数,用于处理 GET 请求,item_id 是一个整数类型的路径参数,q 是一个可选的查询参数。
  • class Item(BaseModel): 使用 Pydantic 定义一个数据模型,用于接收 POST 请求的参数。
  • @app.post("/items/"): 定义一个 POST 请求的路由,路径为 /items/
  • async def create_item(item: Item): 定义一个异步函数,用于处理 POST 请求,item 是一个 Item 类型的参数。

3. 运行应用

uvicorn main:app --reload
  • main: 指的是 main.py 文件。
  • app: 指的是 main.py 文件中的 app 实例。
  • --reload: 开启自动重载,当你修改代码时,服务器会自动重启。

4. 访问 API

在浏览器中访问以下地址:

  • http://127.0.0.1:8000/: 你会看到 {"Hello": "World"}
  • http://127.0.0.1:8000/items/5?q=somequery: 你会看到 {"item_id": 5, "q": "somequery"}
  • http://127.0.0.1:8000/docs: 你会看到 Swagger UI 文档,可以方便地测试你的 API。
  • http://127.0.0.1:8000/redoc: 你会看到 ReDoc 文档,另一种风格的 API 文档。

5. 发送 POST 请求

你可以使用 curl 或者 Postman 发送一个 POST 请求到 http://127.0.0.1:8000/items/,请求体如下:

{
  "name": "Foo",
  "description": "A very nice Item",
  "price": 50.2,
  "tax": 3.2
}

你会得到如下响应:

{
  "name": "Foo",
  "description": "A very nice Item",
  "price": 50.2,
  "tax": 3.2,
  "price_with_tax": 53.4
}

恭喜你!🎉 你已经成功搭建了你的第一个 FastAPI API!

三、 深入探索:FastAPI 的核心特性

搭建了一个简单的 API 之后,咱们来深入了解一下 FastAPI 的核心特性,看看它到底有哪些过人之处。

1. Pydantic:数据验证的瑞士军刀

Pydantic 是 FastAPI 的灵魂伴侣,它负责处理数据的验证和序列化。想象一下,你是一位海关官员,负责检查入境旅客的行李。Pydantic 就像你的X光机,能快速识别出违禁品(不符合规范的数据),并给出详细的报告。

示例:

from pydantic import BaseModel, validator

class User(BaseModel):
    id: int
    name: str
    signup_ts: datetime | None = None
    friends: list[int] = []

    @validator("name")
    def name_must_contain_space(cls, v):
        if " " not in v:
            raise ValueError("must contain a space")
        return v
  • BaseModel: Pydantic 的基类,所有数据模型都必须继承它。
  • id: int: 定义一个整数类型的字段 id
  • signup_ts: datetime | None = None: 定义一个可选的 datetime 类型的字段 signup_ts,默认值为 None。
  • friends: list[int] = []: 定义一个整数类型的列表字段 friends,默认值为空列表。
  • @validator("name"): 定义一个验证器,用于验证 name 字段。
  • def name_must_contain_space(cls, v): 验证器的函数,vname 字段的值。
  • raise ValueError("must contain a space"): 如果 name 字段不包含空格,则抛出一个 ValueError 异常。

Pydantic 的数据验证功能非常强大,可以支持各种数据类型、正则表达式、自定义验证器等等。它可以帮助你编写更加健壮的代码,减少 bug 的产生。

2. 依赖注入:解耦的艺术

依赖注入是一种设计模式,它可以帮助你解耦代码,提高代码的可维护性和可测试性。想象一下,你是一位汽车修理工,你需要更换汽车的轮胎。依赖注入就像你的工具箱,里面装满了各种各样的工具,你可以根据需要选择合适的工具,而不需要自己制造工具。

示例:

from fastapi import Depends, FastAPI

app = FastAPI()

async def common_parameters(q: str | None = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "limit": limit}

@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons
  • Depends(common_parameters): 告诉 FastAPI,read_items 函数依赖于 common_parameters 函数。
  • FastAPI 会自动调用 common_parameters 函数,并将返回值作为 read_items 函数的参数。

通过依赖注入,你可以将公共的逻辑提取出来,并在多个函数中复用,减少代码的冗余。

3. 自动文档:API 的说明书

FastAPI 可以自动生成 Swagger UI 和 ReDoc 文档,让你的 API 拥有完善的说明书。想象一下,你是一位导游,你需要向游客介绍景点的历史和文化。自动文档就像你的讲解词,能清晰地告诉开发者如何使用你的 API。

Swagger UI 和 ReDoc 都是流行的 API 文档生成工具,它们可以根据你的代码自动生成交互式的 API 文档,方便开发者测试和使用你的 API。

四、 进阶技巧:打造高性能 API

掌握了 FastAPI 的基本用法之后,咱们来学习一些进阶技巧,打造高性能的 API。

1. 异步编程:提升并发能力

异步编程是一种编程模型,它可以让你在等待 I/O 操作完成时,继续执行其他任务,从而提高程序的并发能力。想象一下,你是一位咖啡师,你需要同时制作多杯咖啡。异步编程就像你的多线程操作,能让你同时处理多个请求,而不需要等待每个请求完成。

示例:

import asyncio
from fastapi import FastAPI

app = FastAPI()

async def some_process(i: int):
    await asyncio.sleep(1)
    return {"task": i}

@app.get("/tasks/{task_id}")
async def read_task(task_id: int):
    result = await some_process(task_id)
    return {"result": result}
  • async def some_process(i: int): 定义一个异步函数,用于模拟耗时的 I/O 操作。
  • await asyncio.sleep(1): 模拟一个 1 秒的 I/O 操作。
  • @app.get("/tasks/{task_id}"): 定义一个 GET 请求的路由,路径为 /tasks/{task_id}
  • async def read_task(task_id: int): 定义一个异步函数,用于处理 GET 请求。
  • result = await some_process(task_id): 调用 some_process 函数,并等待其完成。

通过异步编程,你可以充分利用 CPU 的资源,提高 API 的并发能力,让你的 API 在面对海量用户时也能游刃有余。

2. 数据库集成:数据持久化

API 通常需要与数据库进行交互,才能实现数据的持久化。FastAPI 可以与各种数据库进行集成,包括关系型数据库(如 MySQL、PostgreSQL)和 NoSQL 数据库(如 MongoDB、Redis)。

示例:

from fastapi import FastAPI, Depends
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session

DATABASE_URL = "sqlite:///./test.db"  # Replace with your database URL

engine = create_engine(DATABASE_URL)
Base = declarative_base()

class Item(Base):
    __tablename__ = "items"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True)
    description = Column(String, nullable=True)

Base.metadata.create_all(bind=engine)

SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

app = FastAPI()

@app.get("/items/{item_id}")
def read_item(item_id: int, db: Session = Depends(get_db)):
    item = db.query(Item).filter(Item.id == item_id).first()
    if item is None:
        return {"error": "Item not found"}
    return item
  • create_engine(DATABASE_URL): 创建一个数据库引擎,用于连接数据库。
  • Base = declarative_base(): 创建一个声明式基类,用于定义数据库模型。
  • class Item(Base): 定义一个数据库模型,继承自声明式基类。
  • SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine): 创建一个会话工厂,用于创建数据库会话。
  • def get_db(): 定义一个依赖注入函数,用于获取数据库会话。
  • db.query(Item).filter(Item.id == item_id).first(): 使用数据库会话查询数据库。

通过数据库集成,你可以将 API 的数据存储到数据库中,实现数据的持久化。

五、 总结:FastAPI,未来可期!

FastAPI 凭借其高性能、易用性和强大的功能,已经成为API开发领域的一颗冉冉升起的新星。它不仅能帮助你快速构建 API,还能让你编写更加健壮、可维护的代码。

未来,随着云计算、人工智能等技术的不断发展,API 的重要性将日益凸显。FastAPI 作为一款优秀的 API 框架,必将在未来的发展中扮演更加重要的角色。

所以,各位代码艺术家们,赶紧拥抱 FastAPI,开启你的 API 开发之旅吧!💪

最后,送大家一句名言:

"Talk is cheap. Show me the code." – Linus Torvalds

希望这篇文章能帮助你更好地了解 FastAPI,并在你的项目中应用它。如果你有任何问题,欢迎在评论区留言,我们一起探讨!😊

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注