FastAPI 基礎架構與非同步處理

如果你是做 AI 應用、爬蟲、或是資料科學,Python 絕對是你的主力語言。但在過去,要用 Python 寫一個後端 API 伺服器,你通常只有兩個選擇:

  1. Django:太過笨重,自帶一堆你用不到的系統。
  2. 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.sleephttpx 套件)。如果一定要用同步函式,請把它宣告為傳統的 def,FastAPI 底層會自動把它丟到 ThreadPool 去執行。

在下一章中,我們將探討 FastAPI 的另一大核心武器:Pydantic 資料驗證。看看它是如何讓你再也不需要手動寫 if request.get("name") is None 這種痛苦的程式碼!