本文 AI 產出,尚未審核

FastAPI 基礎概念(Fundamentals)

FastAPI 是什麼、與 Flask / Django 的比較


簡介

在現代 Web 開發中,API 已成為前後端分離、微服務與行動應用的核心橋樑。
FastAPI 是一套基於 Starlette(非同步網路框架)與 Pydantic(資料驗證)構建的 Python Web 框架,主打 高效能、自動產生 OpenAPI 文件 與 型別提示 的開發體驗。

對於剛接觸 Python Web 框架的開發者,了解 FastAPI 與傳統的 Flask、全功能的 Django 有何不同,有助於在專案初期選擇最適合的工具,減少未來的重構成本。


核心概念

1. 非同步(Async)與高效能

FastAPI 完全支援 async def,在處理 I/O 密集(如資料庫、外部 API)時,可讓單一執行緒同時服務多個請求。
相較之下,Flask 需要額外套件(如 gevent)才能達到類似效果;Django 在 3.1 之後才加入 async 支援,且生態系仍以同步為主。

重點:如果你的服務預期會有大量同時連線,選擇 FastAPI 能直接受惠於 Python 原生的非同步特性。

2. 型別提示 + 自動驗證

FastAPI 以 Python 型別註解 為基礎,自動產生請求參數的驗證與文件。

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    tags: list[str] = []   # 預設值

@app.post("/items/")
async def create_item(item: Item):
    """
    接收 JSON,FastAPI 會自動把它轉成 Item 實例,並驗證欄位類型與限制。
    """
    return {"msg": f"已建立商品 {item.name},價格 {item.price}"}

上述程式碼只寫了型別,FastAPI 會在執行時檢查 name 必須是字串、price 必須是浮點數,若不符合會直接回傳 422 錯誤。

3. 自動產生 OpenAPI 與 Swagger UI

啟動 FastAPI 後,兩條預設路由即可看到 API 文件:

路由 功能
/docs Swagger UI(互動式測試)
/redoc ReDoc(更完整的文件)

只要在程式中加入路由與型別,文件即時更新,省去手寫或維護 Swagger 檔案的時間。

4. 輕量卻可擴充

FastAPI 本身只提供路由、請求/回應、依賴注入(Dependency Injection)等核心功能,其他需求(認證、資料庫、背景工作)都以 Starlette 中間件或第三方套件的方式加入。

功能 Flask Django FastAPI
認證/授權 Flask‑Login、Flask‑JWT Django Auth fastapi‑users、OAuth2
ORM SQLAlchemy、Peewee Django ORM SQLModel、Tortoise‑ORM
背景工作 Celery(需自行整合) Celery、Django‑Q FastAPI + Celery / BackgroundTasks

5. 依賴注入(Dependency Injection)

FastAPI 內建的依賴機制讓共用資源(如 DB 連線、設定)可在路由函式間「注入」而不必使用全域變數。

from fastapi import Depends, FastAPI

def get_db():
    db = ...   # 建立資料庫連線
    try:
        yield db
    finally:
        db.close()

@app.get("/users/{user_id}")
async def read_user(user_id: int, db = Depends(get_db)):
    user = db.query(User).filter(User.id == user_id).first()
    return user

這樣的設計不僅提升可測試性,也讓程式結構更清晰。


程式碼範例

以下提供 5 個實用範例,說明 FastAPI 常見操作與其優勢。

範例 1:最簡單的 Hello World

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def hello():
    return {"message": "Hello, FastAPI!"}

只需要兩行程式,即可啟動一個可即時測試的 API。


範例 2:路由參數與驗證

from fastapi import FastAPI, Path, Query

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(
    item_id: int = Path(..., title="商品 ID", gt=0),
    q: str | None = Query(None, max_length=50)
):
    """
    - `Path` 用於路徑參數驗證(必須大於 0)
    - `Query` 用於查詢字串參數,可設定長度限制
    """
    result = {"item_id": item_id}
    if q:
        result["q"] = q
    return result

透過 Path 與 Query,開發者可以在宣告階段即完成參數驗證,減少手動檢查的程式碼。


範例 3:使用 Pydantic 建立複雜的請求模型

from fastapi import FastAPI
from pydantic import BaseModel, Field, EmailStr

app = FastAPI()

class UserCreate(BaseModel):
    username: str = Field(..., min_length=3, max_length=20)
    email: EmailStr
    password: str = Field(..., min_length=8)

@app.post("/users/")
async def create_user(user: UserCreate):
    # 這裡可以直接使用 user.username、user.email ...
    return {"msg": f"使用者 {user.username} 已建立"}

Pydantic 讓 資料模型、驗證、序列化 同時完成,且自動出現在 Swagger 文件中。


範例 4:依賴注入與資料庫(以 SQLModel 為例)

from fastapi import FastAPI, Depends
from sqlmodel import SQLModel, Session, create_engine, select

DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(DATABASE_URL, echo=True)

def get_session():
    with Session(engine) as session:
        yield session

app = FastAPI()

class Product(SQLModel, table=True):
    id: int | None = Field(default=None, primary_key=True)
    name: str
    price: float

@app.on_event("startup")
def on_startup():
    SQLModel.metadata.create_all(engine)

@app.post("/products/")
async def create_product(product: Product, session: Session = Depends(get_session)):
    session.add(product)
    session.commit()
    session.refresh(product)
    return product

透過 Depends(get_session),每次請求都會得到一個獨立的 DB session,避免共享狀態問題。


範例 5:背景任務(BackgroundTasks)

from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def write_log(message: str):
    with open("log.txt", "a") as f:
        f.write(message + "\n")

@app.post("/notify/")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    # 假設此處呼叫外部郵件服務,時間較長
    background_tasks.add_task(write_log, f"已發送通知給 {email}")
    return {"msg": "通知已排程,請稍後查看信箱"}

使用 BackgroundTasks,可以把不需要即時回應的工作排到請求結束後執行,提升 API 的回應速度。


常見陷阱與最佳實踐

陷阱 說明 解決方案
混用同步與非同步程式碼 在 async 路由中直接呼叫阻塞的函式(如 time.sleep)會阻塞整個事件迴圈。 使用 await asyncio.sleep() 或將阻塞程式碼包在 run_in_threadpool 中。
未正確關閉資源 DB session、檔案句柄等若未在結束時釋放,會造成記憶體泄漏。 利用依賴注入的 yield 方式,確保 finally 區塊執行清理。
過度依賴全域變數 全域的設定或連線在多執行緒環境下不安全。 使用 Depends 或 ContextVar 讓資源在請求範圍內管理。
忽略安全性 直接暴露 CRUD API,未加認證授權。 采用 OAuth2、JWT 或 fastapi-users 套件,配合 Depends 進行權限檢查。
文件未同步 手寫 Swagger 檔案或自行寫說明,易與實際程式碼不符。 依賴 FastAPI 自動產生的 OpenAPI,僅在需要特殊描述時才手動補充。

最佳實踐

  1. 型別註解必寫:讓 FastAPI 發揮自動驗證與文件生成的最大效益。
  2. 盡量使用 async:對 I/O 密集的路由(DB、外部 API)改寫為 async def,配合 async 驅動的套件(如 httpx、databases)。
  3. 分層設計:將路由、服務層(business logic)與資料層分離,利用依賴注入傳遞服務物件。
  4. 測試驅動:FastAPI 支援 TestClient(基於 requests)進行單元測試,建議在開發初期即加入測試。
  5. 使用容器化:將 FastAPI 包裝成 Docker 映像,搭配 Uvicorn/Gunicorn 的多工作者模式(uvicorn workers)部署,可在生產環境取得更高吞吐量。

實際應用場景

場景 為何選 FastAPI
微服務 API 高併發、低延遲、自然支援 JSON Schema(OpenAPI),易於與其他服務(Kubernetes、Istio)整合。
資料科學模型部署 只需要幾行程式把模型封裝成 HTTP 端點,FastAPI 的自動文件讓前端或同事快速了解輸入輸出格式。
行動 App 後端 需要快速回應與 JWT 認證,FastAPI 可在同一程式碼庫內完成認證、授權與資料驗證。
即時訊息/長輪詢 配合 WebSocket(Starlette 原生支援),可在同一框架內同時提供 REST 與即時通訊。
內部管理系統 透過 fastapi-admin、fastapi-users 快速產生 CRUD 後台,減少開發時間。

總結

FastAPI 以 型別提示 + 非同步 為核心,結合 自動產生 OpenAPI、依賴注入 與 輕量可擴充 的設計哲學,為 Python 開發者提供了 比 Flask 更現代、比 Django 更靈活 的選擇。

  • 若你的專案需要 高併發、快速迭代,或是 資料科學模型的即時服務,FastAPI 幾乎是首選。
  • 若你已經在使用 Django 的完整 ORM、Admin 與模板系統,且需求以傳統網站為主,仍可考慮 Django。
  • 若你只需要一個極簡的單頁 API,且不在乎非同步效能,Flask 仍是輕量的好選擇。

最終,選擇框架應該根據專案需求、團隊熟悉度與未來擴充性 來決定。無論是哪一條路,了解 FastAPI 的核心概念與最佳實踐,都能讓你在 Python Web 開發的旅程中走得更遠、更穩。