本文 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

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


範例 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 區塊執行清理。
過度依賴全域變數 全域的設定或連線在多執行緒環境下不安全。 使用 DependsContextVar 讓資源在請求範圍內管理。
忽略安全性 直接暴露 CRUD API,未加認證授權。 采用 OAuth2、JWT 或 fastapi-users 套件,配合 Depends 進行權限檢查。
文件未同步 手寫 Swagger 檔案或自行寫說明,易與實際程式碼不符。 依賴 FastAPI 自動產生的 OpenAPI,僅在需要特殊描述時才手動補充。

最佳實踐

  1. 型別註解必寫:讓 FastAPI 發揮自動驗證與文件生成的最大效益。
  2. 盡量使用 async:對 I/O 密集的路由(DB、外部 API)改寫為 async def,配合 async 驅動的套件(如 httpxdatabases)。
  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-adminfastapi-users 快速產生 CRUD 後台,減少開發時間。

總結

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

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

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