為什麼需要 Pydantic
Python 需要 Pydantic,是因為型別提示(type hints)在執行時不會被檢查:宣告 age: int 之後,傳進字串 "abc" 程式照樣執行,錯誤要到很後面才爆開。Pydantic 在資料「進門」的那一刻依型別驗證並轉換,讓壞資料在邊界就被擋下,而不是在商業邏輯深處造成難以追查的 bug。
型別提示、型別檢查、資料驗證差在哪?
這三個詞常被混用,但負責的時間點與對象完全不同:
| 名稱 | 誰來做 | 什麼時候 | 能擋住什麼 |
|---|---|---|---|
| 型別提示(type hints) | 你寫在程式碼上 | 不執行任何檢查 | 什麼都擋不住,只是說明與 IDE 提示 |
| 型別檢查(type checking) | mypy、Pyright 等工具 | 開發階段(靜態分析) | 自己程式碼裡的型別錯誤 |
| 資料驗證(data validation) | Pydantic | 執行階段 | 來自外部、事先無法預知的資料 |
關鍵在最後一列:API 請求、JSON 檔、環境變數、資料庫查詢結果、LLM 回傳的文字,都是執行時才知道內容的資料,靜態型別檢查器看不到,只有執行期驗證能處理。
沒有 Pydantic 時會發生什麼事?
只用型別提示時,錯誤資料會一路往下流:
from dataclasses import dataclass
@dataclass
class Order:
quantity: int
price: float
order = Order(quantity="3", price="19.9") # 不會報錯!
total = order.quantity * order.price # TypeError:字串不能乘字串
錯誤發生在計算總價那一行,而不是資料進來的地方。真實專案中這兩行可能相隔好幾個檔案,追查成本很高。
改用 Pydantic 後,同樣的資料會在建立物件時就被驗證並轉成正確型別:
from pydantic import BaseModel
class Order(BaseModel):
quantity: int
price: float
order = Order(quantity="3", price="19.9")
print(order.quantity * order.price) # 59.699999999999996,型別已轉成 int 與 float
如果傳入 quantity="three",Pydantic 會立刻丟出 ValidationError,並指出是哪個欄位、為什麼不合法。
Pydantic 適合用在哪些地方?
- Web API:FastAPI 用 Pydantic 模型定義請求與回應格式,自動驗證並產生 OpenAPI 文件。
- 設定管理:
pydantic-settings從環境變數與.env讀取設定,型別錯誤在啟動時就發現。 - 資料管線:讀取 CSV、JSON、外部 API 回應時,先驗證再處理。
- LLM 結構化輸出:要求模型輸出符合 JSON Schema 的資料,再用 Pydantic 驗證,避免手動解析字串。
什麼時候不需要 Pydantic?
資料完全由自己的程式產生、不跨越任何邊界時,驗證是多餘的成本。這時用標準函式庫的 dataclasses 或一般類別即可。原則是:在系統邊界驗證,在內部信任型別。
推薦影音
Corey Schafer:型別提示、型別檢查與資料驗證的差別
簡述:用實例說明三者各自負責什麼,以及為什麼有了 mypy 仍然需要 Pydantic,正好對應本頁第一節。
ArjanCodes:為什麼真實專案需要 Pydantic
簡述:從軟體設計角度示範欄位驗證、模型驗證、自訂序列化與 FastAPI 整合,適合想知道「Pydantic 在大型專案中扮演什麼角色」的讀者。