FastAPI 誕生的緣由

原文:https://fastapi.tiangolo.com/alternatives/

作者:tiangolo

翻譯:somenzz

本文講述了什麼啟發了 FastAPI 的誕生,它與其他替代框架的對比,以及從中汲取的經驗。

簡介

如果不是基於前人的成果,FastAPI 將不會存在。在 FastAPI 之前,前人已經創建了許多工具 。

幾年來,我一直在避免創建新框架。首先,我嘗試使用許多不同的框架,插件和工具來解決 FastAPI 涵蓋的所有功能。

但是有時候,沒有更好的辦法,除了創建具有所有這些功能的東西,從以前的工具中汲取最佳創意,並以最佳方式將它們組合起來,使用以前甚至沒有的語言功能(Python 3.6+ 的類型提示)。

在此之前的一些框架

Django

Django 是最流行的 Python 框架,受到廣泛信任。它可用於構建 Instagram 之類的大型系統。

它與關系數據庫(例如 MySQL 或 PostgreSQL)相對緊密地結合在一起,因此,以 NoSQL 數據庫(例如 Couchbase,MongoDB,Cassandra 等)作為 django 的主存儲引擎並不是一件容易的事。

創建它是為了在後端生成 HTML,而不是創建現代前端(例如 React,Vue.js 和Angular)或與其通信的其他系統(例如 IoT 設備)使用的 API 。

Django REST Framework

Django REST Framework 是一個非常靈活的框架,用於構建 Web API,以改善 Django 的 API 功能。

Mozilla,Red Hat 和 Eventbrite 等許多公司都使用它。

Django REST Framework 是第一個自動生成 API 文檔的框架,自動生成 API 的介面文檔是 FastAPI 框架誕生的緣由之一。

註意

Django REST Framework 框架的作者是 Tom Christie ,Tom Christie 也創造了 Starlette 和 Uvicorn。FastAPI 正是建立在 Starlette 和 Uvicorn 的基礎之上。

啟發 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 文檔。然後我發現 API 文檔有一個標準叫 Swagger ,它使用 JSON 或 YAML 來描述。

並且 Swagger API 的 Web 用戶界面已經被人創建出來了。因此,能夠為 API 生成Swagger 文檔將允許自動使用此 Web 用戶界面。

在某個時候,Swagger 被授予 Linux Foundation,將其重命名為 OpenAPI。這就是為什麼在談論版本 2.0 時通常會說“ Swagger”,對於版本3+來說是“ OpenAPI”。

啟發 FastAPI 地方:

為API規範採用開放標準,而不是使用自定義架構。並集成基於標準的用戶界面工具:

選擇這兩個是因為它們相當受歡迎且穩定,但是通過快速搜索,您可以找到數十個 OpenAPI 的其他替代用戶界面(可以與FastAPI一起使用)。

Flask REST frameworks

有幾個 Flask REST frameworks ,但經過調查和試用,我發現,不少項目都停產或放棄,還存在有一些長期的問題,使得它們並不適合解決前面的問題。

Marshmallow

一個由 API 系統所需的主要功能是數據的序列化,就是把數據從編程語言中的對象轉稱成可以在網路上傳輸的對象,比如數據庫中的數據轉換為 JSON 對象。將 Python 中的datetime 對象轉為字元串,等等。

另外一個功能就是數據的驗證,確保傳入的參數是有效的,例如,有些欄位是一個 int,類型而不是字元串,這在檢測輸入數據是非常有用的。

如果沒有數據驗證,你就必須用手工寫代碼來完成所有的檢查。

這兩點功能就是 Marshmallow 所提供的,這些是一個偉大的圖書館,之前我經常使用它。

Marshmallow 產生之前 Python 還沒有加入類型提示。因此,定義一個 schema 你需要引入 Marshmallow 特定的 utils 的和類。

啟發 FastAPI 地方:

使用代碼來定義提供的數據類型和驗證的 schema,驗證都是自動化的。

Webargs

API 框架需要的另一大功能點是解析從前端發送的請求數據。Webargs (包括Flask) 是提供這一功能的工具,它採用 Marshmallow 做數據驗證。Webargs 和 Marshmallow 的作者是同一個開發人員。這是一個偉大的工具,在 FastAPI 誕生之前,我一直在用它。

啟發 FastAPI 地方:

對輸入的請求數據的自動驗證。

APISpec

Marshmallow 和 Webargs 提供以插件形式提供驗證,解析和序列化。但文檔這塊缺失,然後 APISpec 誕生了。APISpec 可做為很多框架的插件(也是做為 Starlette 插件)。

它的工作方式是,在 Python 的文檔字元串內部使用 YAML 格式的描述來為每一個函數自動生成文檔。它會生成 OpenAPI 的 schemas。這也是它工作在 Flask, Starlette, Responder 等框架上的方式。

缺點是,我們又必須在 Python 的文檔字元串使用 YAML 語法,細微的差別可能導致一些錯誤。如果我們修改參數或 Marshmallow 的 schema,卻忘了還修改 YAML 文檔字元串,生成的模式將被廢棄。

APISpec 和 Marshmallow 的作者是同一個開發者。

啟發 FastAPI 地方:

支持API 的開放式標準。

Flask-apispec

這是一個 Flask 插件,和 Webargs, Marshmallow, APISpec 聯系在一起。

APISpec 使用 Webargs 和 Marshmallow 生產的信息來生成 OpenAPI 的 schemas。

這是一個偉大的工具,非常低估。它應該是比許多 Flask 插件更受歡迎。這可能是由於它的文檔過於簡潔、抽象。

它解決了無需在 Python文檔字元串內編寫YAML(另一種語法)。

在 FastAPI 創建之前,Flask, Flask-apispec, Marshmallow ,Webargs 的聯合是我經常用到的後端技術棧。使用這些框架,我們創建了幾個 Flask 的全棧生成器。以下是是我和幾個外部團隊一直到現在都使用的主要技術棧:

啟發 FastAPI 地方:

自動生成的 OpenAPI 模式,使用相同的代碼定義序列化和驗證。

NestJS (and Angular)

這很跟 Python 沒有關系,NestJS是一個JavaScript(TypeScript)NodeJS 框架,受Angular 啟發。它實現了一些功能,類似的,可以將它們用在 Flask-apispec 上。

它具有一個集成的依賴註入系統,同樣是受 Angular 啟發。像我知道的的其他依賴註入系統一樣,它需要預註冊,所以,它添加了冗長而重復的代碼。

由於參數由 TypeScript 類型(就像 Python 的類型提示一樣)描述,對編輯器的支持是相當不錯的。

TypeScript 的數據在編譯至 JavaScript 後並不保存,它不能依靠類型來實現驗證,序列化和文檔。由於這一點,一些設計決策,比如獲得的驗證,序列化和自動模式生成,它需要在很多地方加裝飾器。因此,它變得相當冗長。

對於嵌套模式它不能處理的非常好。因此,如果 JSON 體內又有 JSON 對象,這又是嵌套JSON對象JSON對象,它不能很好的生成文檔和驗證。

啟發 FastAPI 地方

使用 Python 類型提示可以提供很大的編輯器支持。

有一個強大的依賴註入系統。找到一種方法,以盡量減少重復的代碼。

Sanic

這是首批基於 asyncio 的極端快速 Python 框架之一。它和 Flask 非常相似。

它使用的 uvloop 而不是 Python 默認的循環,因此非常快。它啟發了 Uvicorn 和 Starlette 的創建,後者在開放的基準方面比 Sanic 還要快。

啟發 FastAPI 地方

找到一個擁有極端性能表現的方法。

這就是為什麼 FastAPI 基於 Starlette,因為它是目前性能最高的框架(由第三方測試基準)。

Falcon

Falcon 是另一個高性能的 Python 框架,它被設計成微型的做為其他框架的基礎,就像 Hug。

它使用以前的 WSGI 標準,這是一個同步框架,所以它不能處理像 WebSockets 和其他異步請求,不管怎麼說,它仍然有非常好的性能表現。

它被設計為具有接收兩個參數的函數,一個“請求”和一個“響應”。然後,您從請求中“讀取”部分,並將“部分”“寫入”響應。由於這種設計,不可能用標準Python類型提示將請求參數和主體聲明為函數參數。

因此,數據驗證,序列化和文檔編制必須以代碼而非自動完成。或者必須像 Hug 框架這樣將它們實現為 Falcon 之上。在受 Falcon 設計啟發的其他框架中,也是有一個請求對象和一個響應對象作為參數。

啟發 FastAPI 地方

尋找獲得出色性能的方法。

像 Hug(基於Falcon ) 一樣,FastAPI 在函數中聲明一個 response 參數。

在 FastAPI 這個是可選的,並且主要用於設置 Header,cookie 和備用狀態代碼。

Molten

我在構建 FastAPI 的最初階段發現了 Molten 。它們具有非常相似的想法:

  • 基於Python類型提示。
  • 基於這些類型提供驗證和生成文檔。
  • 依賴註入系統。

它沒有使用像第三方庫(如Pydantic)提供數據驗證,序列化和文檔,它有自己的庫。因此,這些數據類型定義將不太容易重用。

它需要更多詳細的配置。並且由於它基於WSGI(而不是ASGI),因此其設計目的並不是要利用 Uvicorn,Starlette和Sanic 等工具提供的高性能能力。

依賴註入系統需要對依賴項進行預註冊,並且將基於已聲明的類型解決依賴問題。因此,不可能聲明多個組件來提供一個特定的類型。

路由在一個單獨的地方聲明,函數在另一個地方使用,(而不是在函數頂部使用裝飾器)。比起Flask(和Starlette)的實現方式,這更像 Django 的實現方式。它降低了代碼之間的耦合程度。

啟發 FastAPI 地方

使用模型欄位的默認值為數據類型定義額外的驗證,對編輯器支持更加友好,在 Pydantic 之前,這是不可行的。

這一點實際上也促進了 Pydantic 的部分模塊更新,以支持相同的驗證聲明樣式(所有這些功能現在在 Pydantic 中已經可用)。

Hug

Hug 是最早使用 Python 類型提示實現API參數類型聲明的框架之一。這是一個好主意,啟發了其他工具也這樣做。

它在聲明中使用了自定義類型,而不僅是 Python 的標準類型,但這仍然是巨大的進步。

它也是第一個生成自定義模式的框架,該自定義模式以 JSON 聲明整個 API。

它不是基於 OpenAPI 和 JSON Schema 之類的標準。因此,將其與 Swagger UI 等其他工具集成並不是一件容易的事。但這又是一個非常創新的想法。

它具有一個有趣而罕見的功能:使用相同的框架,可以創建 API 以及 CLI。

由於它基於先前的 Python 同步 Web 框架(WSGI)標準,盡管它仍然具有高性能,但它不能處理 Websockets 和其他事物。

啟發 FastAPI 地方

Hug 啟發了 APIStar 的各個部分,Hug 與 APIStar 是我發現最有前途的工具之一。

Hug 啟發了 FastAPI 使用 Python 類型提示來聲明參數,並自動生成定義 API 的模式。

Hug 啟發了 FastAPI 在函數中聲明一個 response 參數在用於設置標頭和 cookie。

APIStar(<= 0.5)

在決定構建 FastAPI 之前,我發現了APIStar 服務器。它幾乎滿足了我的所有需求,並且設計出色。

這是最早使用Python類型提示聲明參數和請求的框架之一(在NestJS和Molten之前)。我在發現 Hub 框架的同時也發現了它。但是 APIStar 使用了OpenAPI 標準。

基於相同的類型提示,它擁有自動化的數據驗證,數據序列化和 生成 OpenAPI 的模式。

主體模式的定義沒有使用 Python 的類型提示,它與 Marshmallow 有點相似,因此,對編輯器的支持不會那麼好,但是 APIStar 仍然是最好的選擇。它具有最佳性能基準(僅被 Starlette 超越)。

最初,它沒有自動化 API 文檔的 Web UI,但我知道我可以向其中添加 Swagger UI。它有一個依賴註入系統。與上面討論的其他工具一樣,它需要組件的預註冊。但是,這仍然是一個很棒的功能。

我從未在完整的項目中使用過它,因為它沒有安全性集成,因此,我無法用基於 Flask-apispec 的全棧生成器替換我擁有的所有功能。我在項目積壓中創建了添加該功能的請求。

但是隨後,該項目的重點轉移了。它不再是一個API Web 框架,因為創建者需要專註於Starlette。現在,APIStar 是一組用於驗證 OpenAPI 規範的工具,而不是 Web框架。

APIStar 是由 Tom Christie 創建的,他也創建了以:

  • Django REST框架
  • Starlette(FastAPI所基於的)
  • Uvicorn(由 Starlette 和 FastAPI 使用)

啟發 FastAPI 地方

我認為用相同的 Python 類型聲明多個內容(數據驗證,序列化和文檔),同時又提供了強大的編輯器支持,這是非常絕妙的主意。

在長時間尋找相似的框架並測試了許多不同的替代方案之後,APIStar 是最佳的選擇。然後,APIStar 不再作為服務器存在,然後 Starlette 出現了,並且為此類系統提供了新的更好的基礎。那是構建FastAPI的最終靈感。

我認為,FastAPI 是 APIStar 的“精神上的繼任者”,同時基於對所有這些先前工具的學習,在改進和增加功能,鍵入系統和其他部分的同時,也是如此。

FastAPI 使用的框架

Pydantic

Pydantic 是一個庫,基於Python類型提示來定義數據驗證,序列化和文檔(使用JSON模式)。這使其非常直觀。它可與 Marshmallow 媲美。盡管在基準測試中它比Marshmallow 更快。並且由於它基於相同的Python類型提示,因此對編輯器的支持非常棒。

FastAPI使用它來處理所有數據驗證,數據序列化和自動模型文檔(基於JSON Schema)。

然後,FastAPI 會獲取該 JSON Schema 數據並將其放入OpenAPI 中,除此之外它還會執行其他所有操作。

Starlette

Starlette 是一種輕量級的 ASGI 框架/工具包,是構建高性能 asyncio 服務的理想選擇。

它非常簡單直觀。它的設計易於擴展,並具有模塊化組件。

它具有:

  • 令人印象深刻的性能。
  • WebSocket支持。
  • GraphQL支持。
  • 處理中的後台任務。
  • 啟動和關閉事件。
  • 測試基於 requests 的客戶端。
  • CORS,GZip,靜態文件,流式響應。
  • 會話和 Cookie 支持。
  • 100% 的測試覆蓋率。
  • 100% 類型註釋的代碼庫。
  • 零硬依賴性。

Starlette 是目前測試最快的 Python 框架。只有 Uvicorn 超越了它,Uvicorn 不是框架,而是服務器。

Starlette 提供了所有基本的 Web 微框架功能。但是它不提供自動數據驗證,序列化或API 文檔。

這是 FastAPI 在頂部添加的主要內容之一,全部基於Python類型提示(使用Pydantic)。以及依賴註入系統,安全實用程式,OpenAPI 模式生成等。

技術細節: ASGI 是 Django 核心團隊成員開發的新“標準”。盡管他們正在這樣做,但它仍然不是“ Python標準”(PEP)。但是,它已經被多種工具用作“標準”。這可以大大提高互操作性,因為您可以將 Uvicorn 切換到任何其他 ASGI 服務器(例如 Daphne 或 Hypercorn),也可以添加與ASGI相容的工具,例如 python-socketio。

FastAPI 使用它來處理所有核心 Web 部件。在頂部添加功能。類 FastAPI 本身直接繼承Starlette。因此,使用 Starlette 可以執行的任何操作,都可以直接使用 FastAPI 進行

Uvicorn

Uvicorn 是基於 uvloop 和 httptools 構建的如閃電般快速的 ASGI 服務器。它不是Web框架,而是服務器。例如,它不提供用於按路徑進行路由的工具。那是像 Starlette(或FastAPI)這樣的框架可以提供的。它是 Starlette 和 FastAPI 的推薦服務器。

FastAPI 推薦它為主 Web服務器運行 FastAPI 應用程式。您可以將其與 Gunicorn 結合使用,以擁有異步多進程服務器。在“ 部署” 部分中查看更多詳細信息。