本文為 AI 描述優化 api 設計 系列文,第 3 篇:
- 如何設計一個商品描述優化 API?—— 完整指南
- 設計 AI 優化商品描述的 Prompt
- FastAPI:高效且易用的 Python Web 框架 👈進度
- 介紹 Uvicorn:高效能 ASGI 伺服器
- Uvicorn 監聽 0.0.0.0,但為何 API 只能用 127.0.0.1 訪問?
- Tenacity:強大的 Python 重試機制庫
- FastAPI 建立商品描述優化 API
- 介紹 pytest:Python 測試框架的強大選擇
- Python httpx 完整指南:高效的 HTTP 客戶端
- Pytest-Benchmark:高效能測試的基準分析工具
- 深入解析 monkeypatch:Python 測試中的強大工具
- API 自動化測試與效能優化
建議閱讀本文前,先具備 聊天機器人-建議回復 相關系列文的概念。
隨著 Web 應用程式的發展,後端框架的選擇越來越多,而 Python 在這方面的生態系統也日趨成熟。其中,FastAPI 是近年來備受關注的一款 高效、易用且支援異步處理 的 Web 框架。
相較於 Flask 和 Django,FastAPI 提供更快的執行速度、更簡潔的代碼結構,並內建強大的數據驗證機制,使開發者能夠更輕鬆地開發高效能的 API 服務。
在這篇文章中,我們將深入介紹 FastAPI 的核心特性、優勢,以及如何開始使用它來開發 Web API。
FastAPI 是什麼?
FastAPI 是一款基於 Python 3.7+ 開發的現代 Web 框架。
它利用 Python 的型別註解(Type Hints),結合 Pydantic 進行數據驗證,並使用 Starlette 作為底層框架來處理異步請求,從而提供高效能的 API 服務。
它的主要特點包括:
- 極速性能:基於 ASGI 架構,執行速度接近 Node.js 和 Go。
- 簡單易用:類似 Flask 的語法風格,開發體驗優秀。
- 內建數據驗證:透過 Pydantic 自動驗證請求和回應數據格式。
- 自動生成 API 文件:支援 OpenAPI(Swagger UI)和 ReDoc。
- 內建異步處理:可透過
async和await進行高效異步請求處理。
FastAPI 的設計理念是讓開發者可以 寫更少的代碼,獲得更多的功能,同時保持程式的可讀性和可維護性。
FastAPI 的優勢
高效能與異步支持
在傳統的 Web 框架(如 Flask 和 Django)中,請求的處理方式通常是「同步」的,這意味著 伺服器在處理某個請求時,會一直等到這個請求完全執行完畢,才能開始處理下一個請求。
如果有大量使用者同時訪問,這種同步方式會讓伺服器的反應變慢,甚至導致請求堆積,影響整體效能。
而 FastAPI 採用了 Starlette 作為底層架構,支援 ASGI(Asynchronous Server Gateway Interface),這讓它能夠使用「非同步(Asynchronous)」的方式來處理請求。
簡單來說,非同步請求處理允許伺服器同時處理多個請求,而不需要等待每個請求的完整執行結果,這樣就能大幅提升應用程式在高併發(即短時間內大量使用者訪問)場景下的效能。
例如:
- 傳統同步處理:
- 使用者 A 發送請求 → 伺服器開始處理 A 的請求 → A 的請求執行完成 → 伺服器才能處理使用者 B 的請求。
- 如果 A 的請求需要 5 秒才能完成,B 就必須等 5 秒後才能開始執行,這會導致整體效能下降。
- FastAPI 的非同步處理:
- 使用者 A 發送請求 → 伺服器開始處理 A 的請求,但如果 A 的請求需要等待資料庫回應或執行其他耗時操作,伺服器不會閒置,而是同時開始處理 B 的請求。
- 這樣,即使 A 的請求需要 5 秒才能完成,B 仍然可以即時獲得處理,不會受到影響。
這種方式非常適合處理 即時應用(如聊天應用、即時通知)、高流量 API 服務,以及 需要大量與資料庫、外部 API 互動的系統,因為它能夠充分利用系統資源,提高整體吞吐量。
內建數據驗證與序列化
在開發 API 服務時,我們通常需要驗證使用者傳入的數據是否符合規範,例如:
- 註冊帳號時,確保使用者名稱是字串,年齡是數字,電子郵件格式正確。
- 上傳商品資訊時,確保價格是數字,名稱不能為空等。
在許多傳統 Web 框架中,開發者必須手動編寫大量的驗證邏輯,例如:
def validate_user(name, age):
if not isinstance(name, str):
return "name 必須是字串"
if not isinstance(age, int):
return "age 必須是整數"
return "驗證通過"
這樣的代碼不僅冗長,還容易出錯,且不同 API 可能需要重複相似的驗證邏輯,導致開發和維護成本增加。
FastAPI 使用 Pydantic 來自動處理數據驗證,開發者只需要定義一個數據模型,框架就會自動驗證請求是否符合規範。例如:
from pydantic import BaseModel
class User(BaseModel):
name: str # name 必須是字串
age: int # age 必須是整數
@app.post("/users/")
async def create_user(user: User):
return {"name": user.name, "age": user.age}
當使用者發送不符合規範的數據時,FastAPI 會自動回傳錯誤訊息,開發者無需手動檢查。例如,假設請求的 JSON 數據如下:
{
"name": 123,
"age": "twenty"
}
FastAPI 會自動回應:
{
"detail": [
{
"loc": ["body", "name"],
"msg": "string type expected",
"type": "type_error.str"
},
{
"loc": ["body", "age"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
這樣一來,開發者不需要再額外編寫驗證邏輯,既能保證數據的正確性,又能提升開發效率。
補充:Pydantic 是什麼?
Pydantic 是由 Samuel Colvin 開發的一個 Python 庫,主要用於:
- 數據驗證(Validation):確保請求或回應的數據類型正確,例如
age必須是int,- 數據解析(Parsing):自動將輸入數據轉換為正確的 Python 類型,例如
age="25"(字串)會自動轉換為age=25(整數)。Pydantic 的核心概念是 使用 Python 的型別註解(Type Hints)來定義數據模型,並自動進行驗證。例如:
from pydantic import BaseModel class User(BaseModel): name: str age: int這樣,當我們用
User(name="Alice", age="25")建立物件時,Pydantic 會自動將age轉換為整數。如果數據不符合要求,它會拋出錯誤。FastAPI 如何使用 Pydantic?
FastAPI 內建整合了 Pydantic,並將它用於處理 HTTP 請求的數據驗證。
例如,當我們建立一個 API 來接收使用者資料時,FastAPI 會自動使用 Pydantic 來驗證請求數據:
from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() # 定義 Pydantic 數據模型 class User(BaseModel): name: str age: int # FastAPI 會自動使用 Pydantic 來驗證請求數據 @app.post("/users/") async def create_user(user: User): return user當客戶端發送 正確 的 JSON 請求:
{ "name": "Alice", "age": 25 }FastAPI 會正常接收並回應:
{ "name": "Alice", "age": 25 }但是,如果客戶端發送 錯誤類型 的數據,例如
age是字串而不是整數:{ "name": "Alice", "age": "twenty-five" }FastAPI 會自動回應錯誤,這是 Pydantic 進行數據驗證後的錯誤訊息:
{ "detail": [ { "loc": ["body", "age"], "msg": "value is not a valid integer", "type": "type_error.integer" } ] }這代表 開發者不需要手動檢查數據類型,FastAPI + Pydantic 會自動處理,大幅減少開發工作量。
Pydantic 只能用在 FastAPI 嗎?
不是的! Pydantic 是一個通用的 Python 庫,可以獨立於 FastAPI 使用。
例如,它可以用在 Django、Flask,甚至是一般的 Python 專案中,例如用來解析設定檔或 API 回應。
舉例來說,在一般的 Python 應用中,我們可以這樣使用 Pydantic 來驗證數據:
from pydantic import BaseModel class Product(BaseModel): name: str price: float # 手動驗證數據 data = {"name": "Laptop", "price": "999.99"} product = Product(**data) print(product) # name='Laptop' price=999.99 (自動將 price 轉為 float)這段程式碼說明,即使沒有使用 FastAPI,Pydantic 依然可以自動將
"999.99"(字串)轉換成999.99(浮點數),並驗證數據類型。
自動生成 API 文件
開發 Web API 時,文件(Documentation)是不可或缺的,因為它能幫助開發者快速理解 API 的使用方式,例如:
- 有哪些 API 端點(Routes)?
- 每個端點接受哪些參數?類型為何?哪些是必填的?
- 回應的資料格式是什麼?
在傳統開發中,API 文件通常需要手動撰寫,這不僅耗時,還容易與實際 API 產生不一致。
例如,當 API 的請求參數或回應格式變更時,開發者可能忘記更新文件,導致前端或其他開發人員無法正確使用 API。
FastAPI 解決了這個問題——它內建支援 OpenAPI(Swagger UI)與 ReDoc,能夠根據 API 代碼自動生成完整的 API 文檔,讓開發者可以即時查看與測試 API,而不需要額外撰寫文件。
如何使用 FastAPI 自動生成 API 文件?
FastAPI 預設提供兩種 API 文件格式,開發者可以透過以下網址直接訪問:
- Swagger UI(互動式 API 文件):
- 訪問
http://127.0.0.1:8000/docs - 這是一個可視化的 API 測試工具,開發者可以直接在網頁上填入參數並發送請求,查看 API 回應結果。
- 訪問
- ReDoc(適合閱讀的 API 文檔):
- 訪問
http://127.0.0.1:8000/redoc - 這個版本的 API 文件更注重結構化顯示,適合閱讀,但沒有互動測試功能。
- 訪問
API 文件自動生成示例
假設我們定義了一個簡單的 API 來獲取使用者資訊:
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
async def get_user(user_id: int):
return {"user_id": user_id, "name": "Alice", "age": 25}
當我們運行應用程式後,打開 http://127.0.0.1:8000/docs,我們會看到一個自動生成的 API 文件,顯示該端點的詳細資訊,包括:
GET /users/{user_id}- 參數
user_id必須是整數 - 回應格式為 JSON(包含
user_id、name和age)
這樣一來,開發者不需要手動撰寫 API 文件,就能確保 API 的規格始終與實際代碼一致,極大提高開發效率。
強大的型別註解與 IDE 支援
Python 自 3.5 版本開始支援 型別註解(Type Hints),而 FastAPI 充分利用 Python 的型別系統,讓開發者在撰寫 API 時能夠明確定義函數的輸入與輸出類型,這帶來了幾個顯著的優勢:
自動補全與型別檢查
在 PyCharm、VS Code 等現代 IDE 中,當開發者使用 FastAPI 時,因為 API 端點的函數已經明確標註了參數類型,IDE 能夠:
- 提供自動補全(Autocomplete),減少拼寫錯誤。
- 即時檢查代碼錯誤,例如傳遞錯誤的參數類型時,IDE 會直接提示,避免執行時才發現錯誤。
讓 API 更加清晰易懂
假設我們有一個函數來建立使用者,如果沒有型別註解,開發者可能不清楚參數 name 和 age 的類型是什麼:
def create_user(name, age):
return {"name": name, "age": age}
但是如果我們加上型別註解,就能讓 API 的定義更清晰:
def create_user(name: str, age: int) -> dict:
return {"name": name, "age": age}
這樣一來,開發者在使用 API 時,就不會誤傳錯誤的資料類型,例如傳入 name=123,因為 IDE 會立即提示錯誤。
自動生成 API 文件時提供詳細類型資訊
由於 FastAPI 使用型別註解來定義 API 的參數和回應類型,這些資訊也會自動顯示在 Swagger UI 中。例如,如果 age 是 int,Swagger UI 會清楚標示,使用者在測試 API 時,就知道該填入哪種類型的數據。
如何開始使用 FastAPI?
安裝 FastAPI
首先,使用 pip 安裝 FastAPI 和 ASGI 伺服器 Uvicorn(用於運行 FastAPI 應用):
pip install fastapi uvicorn建立第一個 FastAPI 應用
接著,建立一個簡單的 FastAPI 應用,並執行 HTTP 服務:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, FastAPI!"}儲存為 main.py,然後運行:
uvicorn main:app --reload
打開瀏覽器,訪問 http://127.0.0.1:8000,即可看到返回的 JSON 資料。
定義路由與請求參數
FastAPI 支援 動態路由 和 請求參數,例如:
@app.get("/users/{user_id}")
async def get_user(user_id: int, q: str = None):
return {"user_id": user_id, "query": q}
訪問 http://127.0.0.1:8000/users/1?q=hello,將返回:
{
"user_id": 1,
"query": "hello"
}
使用 Pydantic 進行數據驗證
可以透過 Pydantic 定義請求體,確保資料格式正確:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
@app.post("/users/")
async def create_user(user: User):
return {"name": user.name, "age": user.age}
此 API 端點只接受符合 User 模型的 JSON 數據,否則會返回錯誤。
FastAPI 與其他框架的比較
| 特性 | FastAPI | Flask | Django REST Framework |
|---|---|---|---|
| 性能 | 高 | 中 | 低 |
| 異步支援 | 是 | 否 | 部分支持 |
| 內建數據驗證 | 是 | 否 | 是 |
| 自動 API 文檔 | 是 | 否 | 是 |
| 開發效率 | 高 | 中 | 低 |
從上表可以看出,FastAPI 在性能、異步支援和開發效率方面具有顯著優勢,非常適合開發高效能 API 服務。
結論
FastAPI 以其高效、易用、內建數據驗證與異步支持的特性,成為現代 Web API 開發的理想選擇。
它的自動 API 文件生成、型別註解支援和卓越的效能,使其特別適合構建 高併發、數據密集型應用,如 微服務、機器學習 API、金融系統等。
如果你正在尋找一個既能提供 Flask 的靈活性,又能擁有 Django REST Framework 的強大功能,並且具備更高效能的框架,FastAPI 絕對值得一試!