FastAPI:Python 高性能 Web 框架的优雅之选

一、FastAPI简介

FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建基于 Python 的 API。它具有简单易用的特性,同时也提供了高度自动化的文档生成功能,使得开发者可以更加高效地构建和部署 API 服务。功能强大、易于使用且高性能的 Web 框架,适用于构建各种规模的 API 服务。它的简洁语法、自动生成文档和异步支持等特性使得开发 API 更加轻松和愉快

中文文档:https://fastapi.tiangolo.com/zh/

GitHub项目地址:https://github.com/tiangolo/fastapi

1.1 FastAPI 关键特性

  1. 快速高效:基于 Starlette 和 Pydantic 构建,具有高性能和低延迟的特点,支持异步处理请求,利用 Python 的协程提高并发性能。
  2. 简单易用:使用标准的 Python 类型注解来定义 API 的输入和输出参数,无需编写大量的文档和验证代码。
  3. 自动生成文档:通过访问 /docs 路径可以查看自动生成的交互式 API 文档,包含了每个端点的详细说明、请求和响应的模型结构以及示例请求和响应。
  4. 数据验证:利用 Pydantic 提供的数据验证功能,可以自动验证请求数据的格式和类型,并进行数据转换。
  5. 依赖注入:支持依赖注入,可以方便地将依赖项注入到处理函数中,例如数据库连接、配置等。
  6. 类型检查:利用 Python 类型提示和 Pydantic 的数据模型,可以在开发过程中进行类型检查,减少错误和调试时间。
  7. 中间件支持:支持使用中间件扩展框架的功能,例如认证、日志记录等。
  8. 标准化:支持 OpenAPI 规范,可以生成符合规范的 API 文档和客户端代码。

1.2 基于ASGI的异步操作

ASGI的基本概念:

ASGI(Asynchronous Server Gateway Interface)是为解决WSGI在异步环境下的局限性而提出的。与WSGI专注于同步环境不同,它为Python应用提供异步处理机制,支持同步和异步应用,允许异步应用与异步客户端通信。其核心特点是接收到请求后可立即返回响应头,无需等待全部响应内容生成,这对长连接或实时通信应用(如WebSocket和HTTP/2.0)优势显著,能通过异步I/O提高吞吐量和资源利用率。

同步与异步的区别和优缺点

  1. 同步编程:服务器一次只能处理一个请求,等待I/O操作时CPU资源闲置,模型简单但效率低。
  2. 异步编程:允许服务器在等待I/O操作时切换到其他任务,提升并发处理能力,但编程模型复杂,调试和维护难度大,对开发者的异步编程知识要求高。
  3. 异步优点:高并发,能更好地利用服务器资源;用户感觉响应更快,I/O操作不会阻塞主线程。

1.3 为何选择 FastAPI?

在 Web 框架的选择上,性能始终是一个关键考量因素。FastAPI 在这一点上表现尤为突出:

框架请求/秒 (均值)延迟 (ms)异步支持
FastAPI25,0002.1
Flask2,30018.5
Django1,90022.3部分

FastAPI 的天生异步支持使其在处理高并发请求时表现卓越,相比传统的同步框架如 Flask 和 Django,性能提升可达 10 倍以上。

二、安装FastAPI

在开始使用FastAPI之前,我们首先需要安装它。FastAPI可以通过pip轻松安装:

pip install fastapi uvicorn

这里我们同时安装了uvicorn,这是一个高性能的ASGI服务器,用于运行FastAPI应用。

三、第一个FastAPI应用

让我们从一个简单的“Hello, World!”应用开始,感受一下FastAPI的魅力。

ffrom typing import Union
from fastapi import FastAPI

app = FastAPI()


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


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

在这个例子中,我们创建了一个FastAPI应用实例,并定义了一个路由/,当用户访问根路径时,返回一个包含“Hello, World"消息的JSON 对象。

通过以上代码还创建了一个具有以下功能的 API:

  1. 通过 路径 / 和 /items/{item_id} 接受 HTTP 请求。
  2. 以上 路径 都接受 GET 操作(也被称为 HTTP 方法)。
  3. /items/{item_id} 路径 有一个 路径参数 item_id 并且应该为 int 类型。
  4. /items/{item_id} 路径 有一个可选的 str 类型的 查询参数 q。

async 关键字用于定义异步函数。异步函数可以在执行过程中暂停并允许其他代码执行,直到某些条件满足后再恢复执行。在 FastAPI 中,使用 async 可以使函数能够处理异步操作,例如异步的数据库查询、IO 操作等,以提高性能和并发能力。 在这个例子中,read_root 和 read_item 函数都是异步函数,它们使用了 async 关键字来定义。这样的函数可以通过 await 关键字调用其他异步函数,或者执行需要等待的异步操作,而不会阻塞整个应用程序的执行。

uvicorn main:app --reload

要运行这个应用,我们可以使用uvicorn。这里的main是包含FastAPI应用的Python文件名(不带.py后缀),app是FastAPI应用实例的名称。--reload选项会在代码发生变化时自动重启服务器,非常适合开发阶段使用。

如果是服务器运行,只需要执行python3 /path/to/main.py运行起来即可。

Image

四、类型提示和数据验证

4.1 Python类型提示的引入

  1. 类型提示的基础语法: 允许开发者在函数、变量、类等定义处标注预期数据类型,用->符号后跟类型表达式标注函数返回值类型。
def greet(name: str) -> str:    
    return f"Hello, {name}!" 
name: str = "Alice"
  1. 类型提示在开发中的作用: 提高代码可读性,提供安全保障,类型检查工具(如mypy)可在运行前发现类型错误,IDEs利用类型提示提供更准确的代码补全、错误提示和重构建议。
def add(a: int, b: int) -> int:    
    return a + b 
# 使用mypy进行类型检查
# mypy my_script.py

4.2 FastAPI中的Pydantic数据验证

  1. Pydantic模型的创建和使用: Pydantic提供支持类型提示的数据模型类,用于验证和序列化数据,创建时只需继承BaseModel并定义属性及其类型,在FastAPI中可直接引用作为API函数的输入,自动进行数据验证。
from pydantic import BaseModel 
class User(BaseModel):    
    username: str    
    email: str    
    age: int
  1. 数据验证的高级技巧: Pydantic提供自定义验证器、数据转换、字段默认值、字段可选性等高级功能,模型还可配置为递归进行数据验证。
from pydantic import BaseModel, root_validator 
class Item(BaseModel):    
    name: str    
    price: float    
    tax: float = None     
    @root_validator(pre=True)    
    def calculate_tax(cls, values):        
        values['tax'] = values['price'] * 0.1        
        return values 
# 使用FastAPI路径操作装饰器定义API
from fastapi import FastAPI
app = FastAPI() 
@app.post('/items/')
async def create_item(item: Item):    
    return item

五、自动化生成OpenAPI文档

  1. 自动文档的原理和优势

    • 原理:FastAPI利用Python类型提示特性,解析函数中的类型注解自动构建符合OpenAPI规范的文档。通过Pydantic模型定义数据模型,应用启动时读取路由处理函数的参数和返回类型,生成OpenAPI 3.0标准的JSON或YAML文档,用于生成交互式API文档页面。
    • 优势:高效率,减少编写文档的时间和成本;准确性,反映实际运行代码,减少人为错误;交互性,提供交互式探索界面,方便理解和测试;协作性,便于团队共享和协作。
  2. 定制和扩展FastAPI文档

    • 自定义OpenAPI信息:为应用指定自定义的版本、标题等信息。
    • 隐藏特定的路由:定义路由时设置include_in_schema=False参数。
    • 添加额外的OpenAPI信息:使用OpenAPI扩展添加自定义字段。
    • 使用自定义模板:允许使用自定义的Jinja2模板自定义OpenAPI页面显示。

Swagger UI:访问 /docs 获得功能齐全的接口测试界面

ReDoc:访问 /redoc 获得美观的 API 文档展示

Image

六、依赖注入机制

6.1 依赖注入的概念与原理

  1. 依赖注入的定义: 是实现控制反转(Inversion of Control, IoC)的编程技术,将对象的创建和依赖关系管理从应用程序代码中解耦,创建松散耦合的代码,使应用更灵活,易于测试和维护。主要类型有构造器注入(依赖项通过构造函数传递)、属性注入(依赖项作为对象属性设置)、方法注入(依赖项通过对象的方法传递)。

  2. 依赖注入在FastAPI中的实现: FastAPI使用依赖注入系统提供应用所需依赖项,在函数中声明需要的参数,运行时自动解析并提供。依赖可以是任意Python可调用对象,FastAPI会自动处理依赖项的依赖关系。

from fastapi import FastAPI, Depends
from typing import Optional 
app = FastAPI() 
def get_db_connection():    
    return fake_db_connection() 
@app.get("/items/{item_id}")
def read_item(item_id: int, db=Depends(get_db_connection)):    
    # 使用 db 进行数据库操作    
    ...

6.2 高级依赖注入技巧

  1. 非阻塞异步依赖注入: FastAPI支持注入异步函数作为依赖项,使依赖项能执行异步代码。
async def get_async_db_connection():    
    return await fake_async_db_connection() 
@app.get("/async-items/{item_id}")
async def read_async_item(item_id: int, db=Depends(get_async_db_connection)):    
    # 使用异步 db 进行数据库操作    
    ...
  1. 依赖注入的性能优化方法: 可通过缓存依赖项避免在每个请求中重复创建或查询,提高性能。
from fastapi import Depends, FastAPI, Request
from fastapi_cache import FastAPICache
from fastapi_cache.backends.inmemory import InMemoryBackend 
app = FastAPI() 
async def get_current_user(request: Request):    
    # 假设这是一个从请求中获取当前用户的函数    
    ... 
@app.get("/items/{item_id}")
def read_item(item_id: int, user=Depends(get_current_user)):    
    # 使用 user 进行操作    
    ... 
# 在应用启动时
@app.on_event("startup")
async def startup():    
    await FastAPICache.init(InMemoryBackend(), prefix="fastapi-cache")

七、总结

FastAPI是专为构建API设计的现代、高性能Python Web框架,凭借异步支持、类型提示、依赖注入、自动化API文档等核心特性,以及简洁、高效、易于测试的特点,成为构建Web服务的首选工具。

  • 全屏阅读F11
  • 打赏支持
  • 快速评论

评论

评论列表

暂无评论

文章目录

    查看评论