FastAPI 演進史(上):型別提示、PEP 649 與 Pydantic v2

我好幾年來一直避免創造一個新框架。一開始,我試著用許多不同的框架、外掛和工具,解決 FastAPI 涵蓋的所有功能……到了某個時間點,除了自己創造一個東西之外,別無選擇。

FastAPI 作者 Sebastián Ramírez(tiangolo)在官方文件〈歷史、設計與未來〉中寫下的這段自白,道出了這個現代 Python Web 框架的起點。

FastAPI 於 2018 年 12 月正式發布,比起 2010 年問世的 Flask 晚了整整八年。但在 2024 年 JetBrains 的 Python 開發者調查中,FastAPI 以 38% 的使用率超越了 Django(35%)與 Flask(34%),躍升為 Python 生態系中採用度最高的 Web 框架。

FastAPI 能在成熟的 Python Web 市場中迅速普及,關鍵在於精準踩中了三個技術轉捩點:Python 3.6+ 的變數註解語法、Starlette 奠定的非同步 ASGI 基礎,以及 Pydantic 將型別宣告轉化為執行時驗證的能力。

本文為上下兩篇系列文章的上篇,回顧 FastAPI 在 2018 至 2026 年間的技術演進史,探討它如何從一個組合式微框架,發展到與 Pydantic 一同影響 Python 型別註解標準的走向。


站在巨人的肩膀上:APIStar 的空位與 2018 年誕生

FastAPI 在官方文件的致謝與靈感清單中,完整列出了它所借鑑的前輩專案:從 Django REST Framework(DRF)學到自動化 API 文件的價值、從 Flask 繼承簡潔的微框架路由設計、從 Requests 汲取直覺的 HTTP 語意,並從 TypeScript 框架 NestJS 中借鑑依賴注入與編輯器優先的理念。

但在所有靈感來源中,影響最深遠的是 APIStar。FastAPI 官方稱自己為 APIStar 的「精神繼承者」,並留下了一句簡短的評價:

「它的存在,啟發了 FastAPI 的誕生。」(Inspired FastAPI to exist.)

 Tom Christie's Transition (2018)

 +-----------------------+         +-----------------------+
 | APIStar               | Pivoted | Starlette             |
 | (Typed API Framework) | ------> | (Async Toolkit)       |
 +-----------------------+         +-----------------------+
             |                                 |
             | Left the niche open             | ASGI base
             v                                 v
 +---------------------------------------------------------+
 | FastAPI (2018)                                          |
 | - Type hints + Pydantic                                 |
 | - Starlette on steroids                                 |
 +---------------------------------------------------------+

APIStar 是 DRF 作者 Tom Christie 於 2017 年打造的實驗性框架,率先探索「以型別提示宣告 Web API」的可能。然而到了 2018 年 9 月,Tom Christie 宣布將 APIStar 轉型為與框架無關的 API 工具組,並將開發重心轉向新問世的 ASGI 微框架 Starlette。

APIStar 轉型後,以型別提示打造 API 框架的方向留下了空位;同時,Starlette 提供了新的非同步基礎。FastAPI 正是在這兩個條件下誕生。

三個月後的 2018 年 12 月 5 日,Sebastián Ramírez 在 GitHub 提交了第一個 commit,並於 12 月 8 日向 PyPI 發布 FastAPI 0.1.0。


核心設計哲學:型別提示從「註解」化為「規格」

在架構分層上,FastAPI 由底至頂分為三層:

  1. Uvicorn:最底層的高效能 ASGI 伺服器,負責連線管理與網路傳輸。
  2. Starlette:中間層的非同步微框架,提供路由分發、中介軟體(Middleware)與 WebSocket 支援。
  3. FastAPI:最上層的封裝,在 Starlette 基礎上整合資料驗證、依賴注入與 OpenAPI 文件生成。

FastAPI 官方將自己形容為「加了類固醇的 Starlette」(Starlette on steroids)。這意味著 FastAPI 的效能天花板直接取決於 Starlette 與 Uvicorn,而底層的非同步行為與中介軟體機制也與 Starlette 深度綁定。

 +-------------------------+
 | FastAPI                 |
 | - Validation (Pydantic) |
 | - Dependency injection  |
 | - OpenAPI docs (/docs)  |
 +-------------------------+
 | Starlette               |
 | - Routing               |
 | - Middleware            |
 | - WebSockets            |
 | - Background tasks      |
 +-------------------------+
 | Uvicorn                 |
 | - ASGI web server       |
 | - uvloop + httptools    |
 +-------------------------+

FastAPI 的核心做法,是讓 Python 型別提示(Type Hints)不再只是靜態分析的參考,也成為框架驗證請求資料、產生 API 文件的依據。

當開發者在路由中宣告 item_id: int,同一份型別資訊就能用在四個環節:

Sebastián Ramírez 在設計之初,便反覆驗證型別提示在涵蓋約 80% 開發者的主流編輯器中的實際效果。FastAPI 不僅追求伺服器端的高效,更將開發者在編輯器中的流暢度與自動補全體驗視為第一優先順序。


八年演進時間軸:從微框架到現代工具鏈

FastAPI 的版本號碼長期維持在 0.x,但每個次版號的躍升往往伴隨重大的架構迭代。回顧 2018 至 2026 年的發布軌跡,整體演進可劃分為三個關鍵階段:

版本發布日期核心變更與里程碑
0.1.02018-12-08第一個公開發布版本
0.93.02023-03-07引入 lifespan 非同步上下文管理機制
0.95.02023-03-18支援並全面推薦標準 Annotated 語法宣告依賴
0.100.02023-07-07正式支援 Pydantic v2,啟動長期雙軌相容
0.111.02024-05-03推出官方 CLI 工具:fastapi dev 與 fastapi run
0.112.02024-08-02核心套件輕量化,標準功能改為 fastapi[standard]
0.126.02025-12-20正式停止支援 Pydantic v1,最低要求 Pydantic 2.7.0
0.130.02026-02-22導入 Pydantic Rust 引擎序列化 JSON,大幅降低 CPU 開銷
0.135.02026-03-01原生支援 Server-Sent Events(SSE)

階段一:2023 年語法與相容性分水嶺

2023 年是 FastAPI 寫法現代化的關鍵轉折。在短短五個月內,官方相繼推出了 lifespan、Annotated 依賴注入語法,以及對 Pydantic v2 的支援。

早期寫法 user: User = Depends(get_user) 把 Depends 放在參數的預設值位置。直接呼叫函式進行單元測試時,這個參數會拿到 Depends 物件而非真正的使用者資料,產生非預期行為;靜態檢查工具也容易誤判。

0.95.0 改為推薦 Python 標準函式庫的 Annotated[User, Depends(get_user)],把參數型別與 Depends 放在同一個註解中,也更方便跨路由重用型別定義。

同時,0.93.0 棄用了過往分散的 @app.on_event("startup") 與 @app.on_event("shutdown") 事件處理器,改採基於 ASGI 標準的 lifespan 上下文管理器,讓資料庫連線池與全域狀態的生命週期管理更加清晰可控。

階段二:2024 年開發者工具鏈成形

隨著生態系成熟,FastAPI 的著眼點從「框架核心」擴充至「全流程開發體驗」。

官方推出的 CLI(fastapi dev、fastapi run)簡化了傳統 Uvicorn 繁雜的啟動參數,並將常用的選用套件打包為 fastapi[standard],讓開發者在極簡安裝與開箱即用之間取得更靈活的選擇空間。

階段三:2025 至 2026 年清理歷史包袱與效能突破

在維持了兩年半的相容過渡期後,FastAPI 於 2025 年底停止支援 Python 3.8/3.9 與 Pydantic v1。

包袱卸除後,FastAPI 在 0.130.0 中全面整合 Pydantic 底層 Rust 引擎(pydantic-core)的能力:宣告回應模型或 Pydantic 回傳型別的回應,不再經過 Python 層級逐欄位轉換的 jsonable_encoder,而是直接以 Rust 進行 JSON 序列化,使高吞吐 API 的序列化延遲與 CPU 開銷顯著降低。相關歷史細節均完整記錄於 FastAPI 版本發布日誌。


直面語言標準:PEP 563 危機與 PEP 649 的轉折

FastAPI 發展史上影響最深遠的一件事,是它與 Pydantic 聯手改變了 Python 語言特性的走向。

危機爆發:字串化註解的威脅

2017 年提出的 PEP 563(延後求值的型別註解)旨在解決型別循環參考與模組載入效能問題。其做法是在編譯期將所有型別註解轉換為純字串(即 from __future__ import annotations 的行為)。

對純靜態檢查工具(如 mypy)而言,字串化註解影響甚微;但對於在執行時需要解析真實型別物件的 Pydantic 與 FastAPI 而言,字串化意味著執行時必須仰賴昂貴且不穩定的動態 eval()。一旦遇到局部作用域、閉包變數或巢狀型別定義,eval() 便會頻繁失敗。

原定在 Python 3.10 讓所有型別註解都變成字串的這項計畫,一旦實施,將直接癱瘓需要在執行時讀取真實型別的現代 Web 生態。

 Python 3.10 Plan (PEP 563)
 +-------------------------------+
 | Stringified annotations       |
 | def f(x: int) -> str:         |
 | annotations = {'x': 'int'}    |
 +-------------------------------+
                 |
                 | Breaks runtime reflection
                 v
 ❌ Broke Pydantic & FastAPI

 Community Resolution (PEP 649 / 749)
 +-------------------------------+
 | Deferred evaluation           |
 | - Via descriptors (functions) |
 | - Computed only when read     |
 +-------------------------------+
                 |
                 | Preserves real type objects
                 v
 ✅ Adopted in Python 3.14 (2025)

社群協商與指導委員會決策

2021 年 4 月 15 日,Pydantic 作者 Samuel Colvin 在 GitHub 上發布緊急倡議:

「簡而言之,Pydantic 在延後求值的註解下運作不良,未來可能也永遠無法良好運作。」

該議題迅速引發開發者社群與 Hacker News 的廣泛討論。

五天後的 4 月 20 日,Python 指導委員會成員 Thomas Wouters 在 python-dev 郵件討論群中正式宣布撤回 PEP 563 在 Python 3.10 的預設化決策:

「我們在此時此刻的決定是:我們承擔不起 PEP 563 帶來的相容性破壞風險。」

隨後,社群轉向支持 Larry Hastings 提出的 PEP 649(後續由 PEP 749 完善實作細節)。該機制將型別求值包裝為惰性函式,唯有在程式碼明確讀取註解時才進行計算,既避免了循環參考,也保住了在執行時取得真實型別物件的能力。

這場長達數年的討論最終在 Python 3.14(2025 年 10 月發布)定案,PEP 649 正式納入語言標準,而 PEP 563 則被官方標註為「從未成為預設行為,並已由 PEP 649/749 取代」。

這場轉折代表 Python 官方正式承認:執行時型別反射(Runtime Type Reflection)已不再是邊陲特例,而是現代 Python 應用開發的核心基石。


Pydantic v2 遷移:組合式架構的紅利與代價

FastAPI 選擇將資料驗證完全委託給 Pydantic,為框架帶來了極簡的程式碼結構,但同時也意味著 FastAPI 的演進與外部專案深度綁定。

Rust 重寫與相容性挑戰

2023 年 6 月,Pydantic v2 正式發布。為了追求極致效能,Pydantic 將核心驗證邏輯以 Rust 重寫為獨立的 pydantic-core,帶來了顯著的運算效能提升,但伴隨而來的是底層 API 的破壞性變更。

FastAPI 在一週內推出了 0.100.0 支援 Pydantic v2。但為了保護下游龐大的企業應用,Sebastián Ramírez 選擇了長達兩年半的雙軌相容過渡期。

這段過渡分三步進行:2023 年 7 月的 0.100.0 同時支援 v1 與 v2;2025 年 10 月的 0.119.0 允許同一專案混用新舊模型;到 2025 年底的 0.126.0–0.128.0,才正式淘汰 v1 與相容層。FastAPI 因此給了社群與第三方套件時間完成遷移。

這段歷程展現了組合式架構的核心權衡:不自行造輪子,並不代表免除維護成本。框架必須替下游使用者承擔核心相依套件大版本升級的相容代價。


⭐️容器部署哲學:「單容器單行程」的雲原生轉向

對於維運與 DevOps 工程師而言,FastAPI 官方部署建議的變遷,清晰反映了容器化架構在過去數年間的思維演進。

 Phase 1: Multi-Process in Container
 +------------------------------+
 | Single Pod                   |
 | +--------------------------+ |
 | | Gunicorn (master)        | |
 | +--------------------------+ |
 |       |               |      |
 |       v               v      |
 | +----------+    +----------+ |
 | | Worker   |    | Worker   | |
 | +----------+    +----------+ |
 +------------------------------+
                 |
                 v
 Phase 2: Cloud Native (K8s)
 +------------------------------+
 | Kubernetes                   |
 | +--------------------------+ |
 | | HPA scaling              | |
 | +--------------------------+ |
 |     |         |         |    |
 |     v         v         v    |
 | +------+  +------+  +------+ |
 | | Pod  |  | Pod  |  | Pod  | |
 | | (1P) |  | (1P) |  | (1P) | |
 | +------+  +------+  +------+ |
 +------------------------------+

第一階段:以 Gunicorn 管理 Uvicorn Worker

在 FastAPI 初期,Uvicorn 尚不具備完善的行程崩潰重啟機制。當時官方推薦使用 tiangolo/uvicorn-gunicorn-fastapi 映像檔,透過 Gunicorn 主行程來監控並管理多個 Uvicorn worker 行程。

第二階段:棄用多行程映像,叢集部署改採單容器單行程

隨著 Uvicorn 自身穩定度提升以及 Kubernetes 成為部署主流,官方正式將該 Gunicorn 映像宣告棄用,並在官方部署指引中重塑了容器化部署原則:

「如果你使用 Kubernetes 等容器叢集管理系統,請在叢集層級處理副本擴充,每個容器內只需運行單一 Uvicorn 行程。」

這項原則以叢集為前提。若只在單台伺服器上以 Docker Compose 部署,缺少叢集層級的副本與負載平衡,官方文件仍示範在單一容器內以 --workers 啟動多個 worker 行程。

容器內再放一層行程管理器,會增加健康狀態判斷與資源配置的複雜度。改由叢集管理副本、每個容器只執行一個行程後,這三項維運工作更容易對應到 Pod:

維運面向早期多行程容器(Gunicorn + Uvicorn)現代雲原生架構(單容器單行程)
健康檢查易出現「Master 存活但 Worker 崩潰」的灰色狀態探針結果直接對應唯一的行程,容器異常時由 kubelet 重啟
資源隔離多 Worker 共享容器,記憶體預估困難易引發 OOMRequest/Limit 精準對應單一行程
擴充控制需手動計算並調整容器內的 Worker 數量叢集層級由 HPA 依負載自動水平擴充

第三階段:現代 CLI 整合

隨著 fastapi dev 與 fastapi run 的推出,現代 Dockerfile 已簡化為標準宣告:

CMD ["fastapi", "run", "app/main.py", "--port", "80"]

官方在 0.116.0 亦加入 fastapi deploy,將部署路徑進一步延伸至雲端託管服務。


文件即產品:從互動式規格到 Agent Skills

開發者能快速理解並開始使用 FastAPI,文件設計是關鍵原因之一。其文件並非單純的 API 參考手冊,而是漸進式的實戰導引,涵蓋了 Python 型別系統與非同步機制的基礎概念。

隨 API 宣告產生的互動式文件

透過整合 OpenAPI 與 Swagger UI / ReDoc,FastAPI 讓後端工程師無需額外維護 API 文件,啟動服務即可在 /docs 進行互動式除錯。這大幅降低了前後端協作的溝通成本,並使 API 規格能直接作為客戶端程式碼生成工具的輸入來源。

面向 AI 時代的文件演進

隨著專案擴充與 AI 輔助開發的普及,FastAPI 的文件體系經歷了兩次重要迭代:

當程式碼生成日益由 AI 輔助,讓 AI 模型能準確理解並產出符合框架最佳實踐的程式碼,已成為新一代開源專案維持生態競爭力的新面向。


結語:八年演進的三條核心脈絡

回顧 FastAPI 自 2018 年誕生至 2026 年的演進歷程,其發展清晰展現了三條主線:

  1. 全面擁抱並推動 Python 標準:從框架專屬的寫法回歸標準的 Annotated 與 lifespan,甚至反向推動 PEP 649 定案,FastAPI 已成為形塑現代 Python 語言特性的重要力量。
  2. 組合式架構的平衡術:站在 Starlette 與 Pydantic 的基礎上實現快速創新,同時以耐心承擔生態系大版本升級的相容成本。
  3. 從框架邁向全流程開發平台:從單純的路由與驗證框架,擴充為涵蓋 CLI、雲端部署乃至 AI Agent Skills 的全方位現代化工具鏈。

當一個微框架的邊界不斷擴充,並逐步跨足商業託管服務時,開源專案的社群治理機制、商業化路徑、效能競品的挑戰以及在 AI 時代的定位,將面臨哪些全新的矛盾與抉擇?

這些關鍵議題,將在下篇中深入探討。