原文:https://zhuanlan.zhihu.com/p/111710808
簡介
如果不是基於前人的成果,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規範採用開放標準,而不是使用自定義架構。並整合基於標準的使用者介面工具:
•Swagger UI
•ReDoc
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。
它解決了無需在 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 結合使用,以擁有非同步多程序伺服器。在“ 部署” 部分中檢視更多詳細資訊。