FastAPI 基礎架構與非同步處理
如果你是做 AI 應用、爬蟲、或是資料科學,Python 絕對是你的主力語言。但在過去,要用 Python 寫一個後端 API 伺服器,你通常只有兩個選擇:
- Django:太過笨重,自帶一堆你用不到的系統。
- Flask:輕量,但是缺乏內建的資料驗證,且對非同步 (Async) 的支援一直不太好。
這時候,FastAPI 橫空出世了。
FastAPI 是目前 Python 成長最快的 Web 框架。顧名思義,它的特色就是「快」。它不僅運行速度快(底層基於 Starlette 與 Pydantic,效能逼近 Node.js 與 Go),而且「開發速度快」,能自動幫你生成 Swagger API 文件。
這堂課,我們就來建立你的第一個 FastAPI 微服務!
1. 環境建置與安裝
首先,我們需要一個乾淨的 Python 虛擬環境。打開你的終端機:
# 建立虛擬環境 (Mac/Linux)
python3 -m venv venv
source venv/bin/activate
# 建立虛擬環境 (Windows)
python -m venv venv
venv\Scripts\activate
接著,安裝 FastAPI 與它專屬的伺服器引擎 uvicorn:
pip install fastapi "uvicorn[standard]"
[!TIP] 什麼是 Uvicorn? Uvicorn 是一個閃電般快速的 ASGI (Asynchronous Server Gateway Interface) 伺服器。FastAPI 負責處理邏輯,而 Uvicorn 負責監聽 Port 並把 HTTP 請求非同步地轉交給 FastAPI。
2. 建立你的第一個 Hello World API
在專案目錄下建立一個名為 main.py 的檔案:
from fastapi import FastAPI
# 建立 FastAPI 實體
app = FastAPI(
title="Vibe Tutor AI 微服務 API",
description="這是我用 FastAPI 建立的第一個後端伺服器!",
version="1.0.0"
)
# 定義一個 GET 路由
@app.get("/")
async def root():
return {"message": "Hello World! 歡迎來到 FastAPI 的世界。"}
# 定義一個帶有路徑參數的路由
@app.get("/users/{user_id}")
async def read_user(user_id: int):
return {"user_id": user_id, "status": "active"}
就是這麼簡單!沒有複雜的設定檔,直接用 Python 的裝飾器 @app.get 就能定義路由。
3. 啟動伺服器與熱重載 (Hot Reload)
在終端機中輸入以下指令來啟動伺服器:
uvicorn main:app --reload
main:指的是main.py這個檔案。app:指的是我們在程式碼中建立的app = FastAPI()實體。--reload:這是開發時的神兵利器!只要你修改了程式碼並存檔,伺服器就會瞬間自動重啟,不需手動中斷。
當你看到 Uvicorn running on http://127.0.0.1:8000 時,就代表成功了!
4. 自動化 OpenAPI 文件 (Swagger UI)
這是 FastAPI 最讓工程師愛不釋手的殺手級功能。
現在,請打開你的瀏覽器,輸入:
👉 http://127.0.0.1:8000/docs
你會看到一個極其精美的 Swagger UI 介面! FastAPI 自動解析了你的程式碼,幫你生出了這份可以直接在畫面上點擊測試的互動式 API 文件。
你不需要手寫任何一行 Postman 設定,前端工程師(或你的 Next.js 應用)可以直接看這份文件來串接 API。如果你前往 http://127.0.0.1:8000/redoc,還能看到另一種風格的文件格式。
5. 為什麼要寫 async def?(非同步處理)
你會注意到,我們在宣告函式時使用了 async def 而不是傳統的 def。
這就是 FastAPI 效能碾壓 Flask 的核心秘密:非同步 (Asynchronous) 處理。
在過去,如果你的 API 正在執行一個很慢的任務(例如:呼叫 OpenAI API 產生文章,需要等 10 秒鐘),整個伺服器就會「卡住(阻塞)」,其他使用者的請求只能排隊乾等。
使用了 async / await 後,當伺服器在等 OpenAI 回應的這 10 秒鐘裡,它可以把控制權交出來,去接客(處理其他使用者的請求)。這讓 FastAPI 能夠用極少的硬體資源,撐起極高的併發流量。
import asyncio
from fastapi import FastAPI
app = FastAPI()
@app.get("/generate-ai-text")
async def generate_text():
# 模擬一個需要等待 5 秒鐘的 AI 生成任務
print("開始生成...")
await asyncio.sleep(5) # 注意:必須使用 await
print("生成完畢!")
return {"result": "這是一段由 AI 生成的超酷文章。"}
[!WARNING] 千萬別用阻塞函式! 如果你在
async def裡面使用了傳統的time.sleep(5),或是同步的requests.get(),整個伺服器還是會被卡死!你必須使用非同步版本的函式(如asyncio.sleep或httpx套件)。如果一定要用同步函式,請把它宣告為傳統的def,FastAPI 底層會自動把它丟到 ThreadPool 去執行。
在下一章中,我們將探討 FastAPI 的另一大核心武器:Pydantic 資料驗證。看看它是如何讓你再也不需要手動寫 if request.get("name") is None 這種痛苦的程式碼!