跳至内容

替代方案、灵感和比较

FastAPI 的灵感来源、与替代方案的比较以及从中吸取的经验教训。

简介

如果没有他人的先前工作,FastAPI 将不存在。

之前已经创建了许多工具,这些工具有助于启发它的创建。

几年来我一直避免创建新的框架。首先,我尝试使用许多不同的框架、插件和工具来解决 FastAPI 涵盖的所有功能。

但在某个时候,除了创建能够提供所有这些功能的东西之外别无选择,从以前的工具中汲取最佳理念,并以最佳方式将它们结合起来,使用之前甚至不存在的语言特性(Python 3.6+ 类型提示)。

以前的工具

Django

它是最流行的 Python 框架,并得到广泛信任。它用于构建 Instagram 等系统。

它与关系数据库(如 MySQL 或 PostgreSQL)相对紧密耦合,因此,将 NoSQL 数据库(如 Couchbase、MongoDB、Cassandra 等)作为主要存储引擎并不容易。

它是为了在后端生成 HTML 而创建的,而不是为了创建由现代前端(如 React、Vue.js 和 Angular)或其他系统(如 IoT 设备)与其通信的 API 而创建的。

Django REST Framework

Django REST Framework 的创建是为了成为一个灵活的工具包,用于在 Django 下构建 Web API,以提高其 API 功能。

许多公司使用它,包括 Mozilla、Red Hat 和 Eventbrite。

它是自动 API 文档 的第一个示例之一,这恰好是最初启发“寻找”FastAPI 的第一个想法之一。

注意

Django REST Framework 由 Tom Christie 创建。Starlette 和 Uvicorn(FastAPI 基于此)的同一创建者。

"启发 FastAPI"

拥有自动 API 文档 Web 用户界面。

Flask

Flask 是一个“微框架”,它不包含数据库集成,也不包含 Django 中默认提供的许多内容。

这种简单性和灵活性允许执行诸如使用 NoSQL 数据库作为主要数据存储系统之类的事情。

由于它非常简单,因此学习起来相对直观,尽管文档在某些时候会变得有点技术性。

它也常用于其他不一定需要数据库、用户管理或 Django 中预构建的众多功能的应用程序。尽管可以使用插件添加许多这些功能。

部件的这种解耦,以及作为一个可以扩展以完全覆盖所需内容的“微框架”是我想要保留的关键特性。

鉴于 Flask 的简单性,它似乎非常适合构建 API。接下来要找的是 Flask 的“Django REST Framework”。

"启发 FastAPI"

成为一个微框架。使其易于混合和匹配所需的工具和部件。

拥有一个简单易用的路由系统。

Requests

FastAPI 实际上并不是 Requests 的替代品。它们的范围大不相同。

实际上,在 FastAPI 应用程序中使用 Requests 非常常见

但即便如此,FastAPI 也从 Requests 中获得了相当多的灵感。

Requests 是一个用于与 API 交互(作为客户端)的库,而 FastAPI 是一个用于构建 API(作为服务器)的库。

它们或多或少处于相对的两端,彼此互补。

Requests 拥有非常简单直观的的设计,使用起来非常容易,并具有合理的默认值。但同时,它也非常强大且可定制。

这就是为什么,正如官方网站上所说

Requests 是历史上下载次数最多的 Python 包之一

它的使用方法非常简单。例如,要执行 GET 请求,您可以编写

response = requests.get("http://example.com/some/url")

FastAPI 的对应 API 路径操作 可以如下所示

@app.get("/some/url")
def read_url():
    return {"message": "Hello World"}

请注意 requests.get(...)@app.get(...) 之间的相似之处。

"启发 FastAPI"

  • 拥有简单直观的 API。
  • 以直接、简单直观的方式使用 HTTP 方法名称(操作)。
  • 拥有合理的默认值,但支持强大的自定义。

Swagger / OpenAPI

我从 Django REST Framework 期望的主要功能是自动生成 API 文档。

然后我发现有一个使用 JSON(或 YAML,JSON 的扩展)来记录 API 的标准,称为 Swagger。

并且已经创建了一个用于 Swagger API 的 Web 用户界面。因此,能够为 API 生成 Swagger 文档将允许自动使用此 Web 用户界面。

在某个时间点,Swagger 被捐赠给 Linux 基金会,并更名为 OpenAPI。

这就是为什么在谈论 2.0 版时通常说“Swagger”,而在谈论 3.0 及更高版本时说“OpenAPI”。

"启发 FastAPI"

采用并使用开放的 API 规范标准,而不是自定义模式。

并集成基于标准的用户界面工具

选择这两个工具是因为它们相当流行且稳定,但快速搜索一下,您会发现数十种 OpenAPI 的替代用户界面(您可以在 FastAPI 中使用)。

Flask REST 框架

有几个 Flask REST 框架,但在投入时间和精力研究它们之后,我发现许多框架已被停止维护或放弃,并且存在一些悬而未决的问题,导致它们不适合使用。

Marshmallow

API 系统所需的主要功能之一是数据“序列化”,即将数据从代码(Python)转换为可以通过网络发送的内容。例如,将包含数据库数据的对象转换为 JSON 对象。将 datetime 对象转换为字符串等。

API 需要的另一个重要功能是数据验证,确保数据在给定某些参数的情况下有效。例如,某个字段是 int 类型,而不是一些随机字符串。这对于传入数据特别有用。

如果没有数据验证系统,您将不得不手动在代码中进行所有检查。

Marshmallow 就是为了提供这些功能而构建的。它是一个很棒的库,我之前也用过很多次。

但它是在 Python 类型提示出现之前创建的。因此,要定义每个模式,您需要使用 Marshmallow 提供的特定实用程序和类。

"启发 FastAPI"

使用代码定义“模式”,自动提供数据类型和验证。

Webargs

API 需要的另一个重要功能是从传入请求中解析数据。

Webargs 是一个旨在在多个框架(包括 Flask)之上提供此功能的工具。

它在底层使用 Marshmallow 来进行数据验证。并且它是由相同的开发人员创建的。

它是一个很棒的工具,在拥有 FastAPI 之前我用过很多次。

信息

Webargs 由与 Marshmallow 相同的开发人员创建。

"启发 FastAPI"

自动验证传入的请求数据。

APISpec

Marshmallow 和 Webargs 将验证、解析和序列化作为插件提供。

但文档仍然缺失。然后创建了 APISpec。

它是许多框架的插件(并且也有一个 Starlette 的插件)。

它的工作方式是在处理路由的每个函数的文档字符串中使用 YAML 格式编写模式定义。

并生成 OpenAPI 模式。

这就是它在 Flask、Starlette、Responder 等中的工作方式。

但是,我们再次遇到了在 Python 字符串(一个大的 YAML)中使用微语法的问题。

编辑器对此帮助不大。如果我们修改参数或 Marshmallow 模式,但忘记修改该 YAML 文档字符串,则生成的模式将过时。

信息

APISpec 由与 Marshmallow 相同的开发人员创建。

"启发 FastAPI"

支持 API 的开放标准 OpenAPI。

Flask-apispec

它是一个 Flask 插件,将 Webargs、Marshmallow 和 APISpec 结合在一起。

它使用 Webargs 和 Marshmallow 中的信息,使用 APISpec 自动生成 OpenAPI 模式。

它是一个很棒的工具,被低估了。它应该比许多现有的 Flask 插件更受欢迎。这可能是因为它的文档过于简洁和抽象。

这解决了在 Python 文档字符串中编写 YAML(另一种语法)的问题。

在构建 FastAPI 之前,Flask、Flask-apispec 与 Marshmallow 和 Webargs 的组合是我最喜欢的后端技术栈。

使用它导致创建了几个 Flask 全栈生成器。这些是我(和几个外部团队)迄今为止一直在使用的主要技术栈

并且这些相同的全栈生成器是 FastAPI 项目生成器 的基础。

信息

Flask-apispec 由与 Marshmallow 相同的开发人员创建。

"启发 FastAPI"

从定义序列化和验证的相同代码中自动生成 OpenAPI 模式。

NestJS(和 Angular

这甚至不是 Python,NestJS 是一个受 Angular 启发的 JavaScript(TypeScript)NodeJS 框架。

它实现了与使用 Flask-apispec 可以实现的功能类似的功能。

它有一个集成的依赖注入系统,灵感来自 Angular 2。它需要预先注册“可注入对象”(就像我所知道的其他所有依赖注入系统一样),因此,它增加了冗长性和代码重复。

由于参数使用 TypeScript 类型(类似于 Python 类型提示)进行描述,因此编辑器支持非常好。

但是由于 TypeScript 数据在编译成 JavaScript 后不会被保留,因此它不能依赖类型同时定义验证、序列化和文档。由于这一点和一些设计决策,为了获得验证、序列化和自动模式生成,需要在许多地方添加装饰器。因此,它变得非常冗长。

它不能很好地处理嵌套模型。因此,如果请求中的 JSON 主体是一个 JSON 对象,该对象具有内部字段,而这些字段又嵌套了 JSON 对象,则无法对其进行正确记录和验证。

"启发 FastAPI"

使用 Python 类型获得出色的编辑器支持。

拥有强大的依赖注入系统。找到一种方法来最大程度地减少代码重复。

Sanic

它是第一个基于 asyncio 的极速 Python 框架之一。它被设计得非常类似于 Flask。

“技术细节”

它使用 uvloop 而不是默认的 Python asyncio 循环。这就是它如此之快的原因。

它显然启发了 Uvicorn 和 Starlette,它们目前在公开基准测试中比 Sanic 更快。

"启发 FastAPI"

找到一种方法来获得极高的性能。

这就是 FastAPI 基于 Starlette 的原因,因为它是目前最快的框架(由第三方基准测试验证)。

Falcon

Falcon 是另一个高性能 Python 框架,它被设计为最小化,并作为 Hug 等其他框架的基础。

它被设计为具有接收两个参数的函数,一个“请求”和一个“响应”。然后您从请求中“读取”部分内容,并将部分内容“写入”响应。由于这种设计,无法使用标准的 Python 类型提示作为函数参数来声明请求参数和主体。

因此,数据验证、序列化和文档必须在代码中完成,而不是自动完成。或者,它们必须作为 Falcon 之上的框架来实现,例如 Hug。这种相同的区别也发生在其他受 Falcon 设计启发的框架中,这些框架将一个请求对象和一个响应对象作为参数。

"启发 FastAPI"

找到获得出色性能的方法。

与 Hug 一样(因为 Hug 基于 Falcon),启发了 FastAPI 在函数中声明 response 参数。

尽管在 FastAPI 中它是可选的,并且主要用于设置标头、cookie 和备用状态代码。

Molten

我在构建 FastAPI 的初期发现了 Molten。它有一些非常相似的理念

  • 基于 Python 类型提示。
  • 从这些类型中进行验证和文档生成。
  • 依赖注入系统。

它不使用像 Pydantic 这样的第三方数据验证、序列化和文档库,它有自己的库。因此,这些数据类型定义将无法轻松重用。

它需要稍微更冗长的配置。并且由于它基于 WSGI(而不是 ASGI),因此它并非旨在利用 Uvicorn、Starlette 和 Sanic 等工具提供的超高性能。

依赖注入系统需要预先注册依赖项,并且依赖项是根据声明的类型解决的。因此,不可能声明多个提供特定类型的“组件”。

路由在一个地方声明,使用在其他地方声明的函数(而不是使用可以放在处理端点的函数顶部的装饰器)。这更接近 Django 的做法,而不是 Flask(和 Starlette)的做法。它在代码中分离了相对紧密耦合的事物。

"启发 FastAPI"

使用模型属性的“默认”值定义数据类型的额外验证。这提高了编辑器支持,并且在 Pydantic 之前不可用。

这实际上启发了更新 Pydantic 的部分内容,以支持相同的验证声明样式(所有这些功能现在已在 Pydantic 中可用)。

Hug

Hug是最早使用Python类型提示来声明API参数类型的框架之一。这是一个很棒的想法,启发了其他工具也这样做。

它在声明中使用了自定义类型而不是标准的Python类型,但这仍然是一个巨大的进步。

它也是最早生成自定义架构来以JSON形式声明整个API的框架之一。

它不是基于OpenAPI和JSON Schema等标准。因此,将其与其他工具(如Swagger UI)集成起来并不简单。但同样,这是一个非常创新的想法。

它有一个有趣且不常见的特性:使用同一个框架,可以创建API和CLI。

由于它基于之前同步Python Web框架(WSGI)的标准,因此无法处理Websockets和其他内容,尽管它仍然具有很高的性能。

信息

Hug由Timothy Crosley创建,他也是isort的创建者,这是一个用于自动排序Python文件中的导入的强大工具。

"启发FastAPI的想法"

Hug启发了APIStar的部分内容,并且是我发现最有希望的工具之一,与APIStar并列。

Hug帮助启发了FastAPI使用Python类型提示来声明参数,并自动生成定义API的架构。

Hug启发了FastAPI在函数中声明response参数以设置标头和Cookie。

APIStar (<= 0.5)

在决定构建FastAPI之前,我发现了APIStar服务器。它几乎具备我所需的一切,并且拥有出色的设计。

这是我见过的最早使用Python类型提示来声明参数和请求的框架实现之一(在NestJS和Molten之前)。我或多或少是在与Hug同时发现它的。但APIStar使用了OpenAPI标准。

它具有基于相同类型提示的自动数据验证、数据序列化和OpenAPI架构生成功能,这些功能分布在多个地方。

主体架构定义没有使用与Pydantic相同的Python类型提示,它更类似于Marshmallow,因此,编辑器支持不会那么好,但即便如此,APIStar仍然是当时最佳的选择。

它当时拥有最佳的性能基准测试结果(仅次于Starlette)。

最初,它没有自动的API文档Web UI,但我知道可以为它添加Swagger UI。

它有一个依赖注入系统。它需要预先注册组件,就像上面讨论的其他工具一样。但即便如此,它仍然是一个很棒的功能。

我从未能够在完整的项目中使用它,因为它没有安全集成,因此,我无法替换基于Flask-apispec的完整堆栈生成器中我拥有的所有功能。我计划在项目积压中创建一个添加此功能的拉取请求。

但随后,项目的重点发生了转移。

它不再是一个API Web框架,因为创建者需要专注于Starlette。

现在APIStar是一套用于验证OpenAPI规范的工具,而不是Web框架。

信息

APIStar由Tom Christie创建。与创建以下工具的人相同:

  • Django REST Framework
  • Starlette(FastAPI基于它)
  • Uvicorn(Starlette和FastAPI使用它)

"启发 FastAPI"

存在。

使用相同的Python类型来声明多个内容(数据验证、序列化和文档),同时提供出色的编辑器支持,这是一个我认为什么都非常棒的想法。

并且在长时间寻找类似的框架并测试了许多不同的替代方案后,APIStar是当时可用的最佳选择。

然后APIStar停止作为服务器存在,Starlette诞生了,并且成为了此类系统的全新且更好的基础。这是构建FastAPI的最终灵感。

我认为FastAPI是APIStar的“精神继任者”,同时在改进和增加功能、类型系统和其他部分的基础上,吸取了所有这些先前工具的经验教训。

FastAPI使用

Pydantic

Pydantic是一个库,用于基于Python类型提示定义数据验证、序列化和文档(使用JSON Schema)。

这使得它非常直观。

它可以与Marshmallow相媲美。虽然在基准测试中它比Marshmallow更快。并且由于它基于相同的Python类型提示,因此编辑器支持非常好。

"FastAPI使用它来"

处理所有数据验证、数据序列化和自动模型文档(基于JSON Schema)。

FastAPI然后获取该JSON Schema数据并将其放入OpenAPI中,除了它执行的所有其他操作之外。

Starlette

Starlette是一个轻量级的ASGI框架/工具包,非常适合构建高性能的asyncio服务。

它非常简单直观。它旨在易于扩展,并具有模块化组件。

它具有

  • 令人印象深刻的性能。
  • WebSocket支持。
  • 进程内后台任务。
  • 启动和关闭事件。
  • 基于HTTPX构建的测试客户端。
  • CORS、GZip、静态文件、流式响应。
  • 会话和Cookie支持。
  • 100%测试覆盖率。
  • 100%类型注释代码库。
  • 很少的硬依赖项。

Starlette目前是测试速度最快的Python框架。仅次于Uvicorn,Uvicorn不是框架,而是一个服务器。

Starlette提供了所有基本的Web微框架功能。

但它不提供自动数据验证、序列化或文档。

这是FastAPI在其之上添加的主要内容之一,所有这些都基于Python类型提示(使用Pydantic)。此外还有依赖注入系统、安全实用程序、OpenAPI架构生成等。

“技术细节”

ASGI是由Django核心团队成员开发的一种新的“标准”。它仍然不是“Python标准”(PEP),尽管他们正在为此努力。

尽管如此,它已经被多个工具用作“标准”。这极大地提高了互操作性,因为您可以将Uvicorn替换为任何其他ASGI服务器(如Daphne或Hypercorn),或者您可以添加兼容ASGI的工具,例如python-socketio

"FastAPI使用它来"

处理所有核心Web部分。在顶部添加功能。

FastAPI本身直接继承自类Starlette

因此,您可以使用Starlette执行的任何操作,都可以直接使用FastAPI执行,因为它基本上是增强版的Starlette。

Uvicorn

Uvicorn是一个闪电般快速的ASGI服务器,构建于uvloop和httptools之上。

它不是Web框架,而是一个服务器。例如,它不提供按路径路由的工具。这是Starlette(或FastAPI)等框架在其之上提供的功能。

它是Starlette和FastAPI推荐的服务器。

"FastAPI推荐它作为"

运行FastAPI应用程序的主要Web服务器。

您还可以使用--workers命令行选项来拥有异步多进程服务器。

部署部分中查看更多详细信息。

基准测试和速度

要了解、比较并查看Uvicorn、Starlette和FastAPI之间的区别,请查看有关基准测试的部分。