FastAPI 作為一個現代 Python Web 框架,藉由非同步特性及型別提示等機制,在效能和開發效率上取得了平衡。本文不僅介紹了 FastAPI 的核心技術,更涵蓋了從基礎環境設定到大型應用程式架構設計的實務。讀者將瞭解如何運用 Type Hints 提升程式碼品質、利用 asyncio 模組實作非同步處理、透過 ASGI 介面提升 Web 效能,以及如何設計 RESTful API。此外,文章也說明瞭 FastAPI 的依賴管理系統和與 Starlette 的整合方式,並提供大型應用程式架構設計的最佳實踐,包含 APIRouter 模組化、依賴注入、中介層和 CORS 設定等,讓開發者能快速上手並建構高品質的 Web 應用。
使用 FastAPI 開發高效能 Web 應用程式:根據現代化 Python 的非同步 Web 框架
FastAPI 是一個根據現代化 Python 的非同步 Web 框架,旨在提供高效能、易用性和強大的功能。本文將探討 FastAPI 的核心概念、技術原理和實務應用,幫助開發者開發高效能的 Web 應用程式。
Type Hints 與靜態型別檢查
在現代化 Python 開發中,Type Hints 扮演著重要的角色。它允許開發者在程式碼中新增型別提示,提高程式碼的可讀性和可維護性。Type Hints 不僅能夠幫助開發者捕捉型別相關的錯誤,還能夠提升程式碼的自動補全和檔案生成。
from typing import List
def greeting(names: List[str]) -> str:
return 'Hello, ' + ', '.join(names)
內容解密:
此範例展示瞭如何使用 Type Hints 定義函式的引數和傳回值型別。
List[str]
表示 names
引數應該是一個字串列表。
-> str
表示函式將傳回一個字串。
非同步處理與 asyncio 模組
非同步處理是 FastAPI 的一大特色。Python 的 asyncio
模組提供了對非同步程式設計的原生支援,使得開發者能夠編寫高效的非同步程式碼。
import asyncio
async def main():
print('Hello ...')
await asyncio.sleep(1)
print('... World!')
內容解密:
此範例展示瞭如何使用 asyncio
模組編寫非同步函式。
async def
定義了一個非同步函式。
await
用於等待非同步操作的完成。
ASGI 與 Web 框架
ASGI(Asynchronous Server Gateway Interface)是 Python 中用於非同步 Web 應用的標準介面。FastAPI 根據 ASGI 構建,能夠提供高效的非同步處理能力。
RESTful API 與 HTTP 方法
REST(Representational State of Resource)是一種流行的 API 設計風格。FastAPI 支援 RESTful API 的開發,並提供了對各種 HTTP 方法的支援,如 POST、GET、PUT 和 DELETE。
from fastapi import FastAPI
app = FastAPI()
@app.post("/items/")
async def create_item(item: dict):
return item
內容解密:
此範例展示瞭如何使用 FastAPI 定義一個 RESTful API 端點。
@app.post
裝飾器指定了此端點將處理 POST 請求。
async def
定義了一個非同步函式來處理請求。
FastAPI 的依賴管理
FastAPI 提供了一個強大的依賴管理系統,能夠簡化依賴注入的過程。
from fastapi import Depends, FastAPI
app = FastAPI()
def get_query(q: str = None):
return q
@app.get("/items/")
async def read_items(q: str = Depends(get_query)):
return {"q": q}
內容解密:
此範例展示瞭如何使用 FastAPI 的依賴管理功能。
Depends
用於指定依賴函式。
get_query
函式定義了一個依賴,它將被注入到 read_items
函式中。
Starlette 與 FastAPI 的關係
Starlette 是一個輕量級的 ASGI 框架,FastAPI 根據 Starlette 構建,繼承了其高效能和非同步處理能力。
FastAPI 架構圖
graph LR A[Client] -->|Request| B[FastAPI App] B -->|ASGI| C[Starlette] C -->|ASGI| D[Uvicorn] D -->|Response| A
圖表翻譯: 此圖表展示了 FastAPI 的基本架構。客戶端傳送請求到 FastAPI 應用程式,FastAPI 根據 ASGI 與 Starlette 互動,最終透過 Uvicorn 等 ASGI 伺服器傳回回應。
FastAPI 實戰
FastAPI 是一個現代化的 Python Web 框架,以其高效能、易用性和豐富的功能而受到開發者的青睞。在本章中,我們將探討如何設定 FastAPI 的開發環境,並介紹其基本概念。
安裝 FastAPI
要開始使用 FastAPI,首先需要安裝相關的套件。我們需要安裝 fastapi
、uvicorn
和 pydantic
。這些套件分別負責提供 FastAPI 框架、ASGI 伺服器和資料驗證功能。
pip install fastapi uvicorn pydantic
驗證安裝
安裝完成後,我們可以透過建立一個簡單的應用程式來驗證 FastAPI 是否正確安裝。
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
執行以下指令啟動伺服器:
uvicorn main:app --reload
開啟瀏覽器並存取 http://127.0.0.1:8000/
,應該可以看到傳回的 JSON 資料:{"Hello": "World"}
。
內容解密:
pip install fastapi uvicorn pydantic
:這行指令用於安裝 FastAPI 及其依賴的套件。其中,fastapi
是框架本身,uvicorn
是 ASGI 伺服器,而pydantic
用於資料驗證。from fastapi import FastAPI
:匯入 FastAPI 類別,這是建立 FastAPI 應用的基礎。app = FastAPI()
:例項化一個 FastAPI 應用物件。@app.get("/")
:這是一個路徑操作裝飾器,用於將函式read_root
與根路徑/
繫結,並指定 HTTP 方法為 GET。uvicorn main:app --reload
:使用 Uvicorn 伺服器執行應用,並啟用自動過載功能,以便在程式碼變更時自動重啟伺服器。
FastAPI 基本功能與路徑引數
在本章中,我們將探討 FastAPI 的基本功能,包括路徑引數、查詢引數和請求體。
路徑引數
路徑引數是用於捕捉 URL 路徑中的變數部分。FastAPI 利用 Python 的型別提示(Type Hints)來解析和驗證這些引數。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
內容解密:
@app.get("/items/{item_id}")
:這裡的{item_id}
是一個路徑引數,FastAPI 會自動捕捉並傳遞給read_item
函式。item_id: int
:使用型別提示指定item_id
的型別為整數,FastAPI 會自動進行型別驗證。
查詢引數
查詢引數是用於在 URL 中傳遞額外資料的方式,通常用於過濾或排序資料。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
def read_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
內容解密:
skip: int = 0, limit: int = 10
:這裡定義了兩個查詢引數skip
和limit
,並分別設定了預設值。- 當存取
/items/?skip=5&limit=20
時,skip
和limit
的值會被解析並傳遞給read_items
函式。
請求體與 Pydantic 模型
請求體是用於在 HTTP 請求中傳遞複雜資料的機制。FastAPI 使用 Pydantic 模型來定義和驗證請求體的結構。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.post("/items/")
def create_item(item: Item):
return item
內容解密:
class Item(BaseModel)
:定義了一個 Pydantic 模型Item
,包含三個欄位:name
、price
和is_offer
。item: Item
:在路徑操作函式中使用Item
模型作為引數型別,FastAPI 會自動解析和驗證請求體中的 JSON 資料。
範本引擎與靜態資源
在本章中,我們將介紹如何在 FastAPI 中使用範本引擎和提供靜態資源。
使用 Jinja2 範本引擎
首先,需要安裝 Jinja2 和 aiofiles:
pip install jinja2 aiofiles
然後,可以建立一個簡單的範本並渲染它:
from fastapi import FastAPI, Request
from fastapi.templating import Jinja2Templates
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/items/{id}")
def read_item(request: Request, id: str):
return templates.TemplateResponse("item.html", {"request": request, "id": id})
內容解密:
templates = Jinja2Templates(directory="templates")
:初始化 Jinja2 範本引擎,並指定範本目錄。return templates.TemplateResponse("item.html", {"request": request, "id": id})
:渲染指定的範本並傳回回應。
大型應用程式架構
在開發複雜的大型應用程式時,良好的架構設計是確保專案可維護性和可擴充套件性的關鍵。本章將探討如何使用FastAPI構建更大規模的應用程式。
單檔案應用程式的侷限性
在小型專案中,將所有程式碼放在單一檔案中是可行的。然而,隨著專案規模的擴大,這種做法會導致程式碼難以維護和理解。FastAPI提供了多種機制來幫助組織大型應用程式。
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
內容解密:
此範例展示了最基本的FastAPI應用程式。隨著功能的增加,這種單檔案結構會變得難以管理。
使用APIRouter進行模組化
APIRouter允許我們將相關的路徑操作分組到不同的模組中。這種模組化的設計使得大型應用程式的組織更加清晰。
# users.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/users/")
def read_users():
return [{"username": "John"}]
@router.get("/users/{user_id}")
def read_user(user_id: int):
return {"username": "John", "user_id": user_id}
內容解密:
此範例定義了一個處理使用者相關操作的APIRouter。我們可以將不同的業務邏輯分離到不同的模組中。
將APIRouter整合到主應用程式
# main.py
from fastapi import FastAPI
from users import router as users_router
app = FastAPI()
app.include_router(users_router)
@app.get("/")
def read_root():
return {"message": "Hello World"}
內容解密:
透過include_router
方法,我們將users_router
註冊到主應用程式中。這樣,/users/
和/users/{user_id}
路徑就變成了應用程式的一部分。
路由器套件結構
對於更大型的應用程式,我們可以使用套件來組織多個APIRouter。
project/
main.py
app/
__init__.py
routers/
__init__.py
users.py
items.py
# app/routers/users.py
from fastapi import APIRouter
router = APIRouter()
# ... 定義路徑操作
# main.py
from fastapi import FastAPI
from app.routers import users, items
app = FastAPI()
app.include_router(users.router)
app.include_router(items.router)
內容解密:
這種結構允許我們將不同的功能模組化,每個模組可以獨立開發和測試。
掛載子應用程式
FastAPI允許我們掛載多個子應用程式,這對於構建微服務架構非常有用。
# main.py
from fastapi import FastAPI
app = FastAPI()
from app.internal.admin import admin_app
app.mount("/admin", admin_app)
內容解密:
透過mount
方法,我們將admin_app
掛載到/admin
路徑下。這使得/admin
下的所有路徑操作由admin_app
處理。
相依性注入
相依性注入是FastAPI的一個強大功能,它允許我們以宣告式的方式管理函式或路徑操作之間的依賴關係。
from fastapi import Depends, FastAPI
app = FastAPI()
async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):
return commons
@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
return commons
內容解密:
common_parameters
函式定義了共同的引數,read_items
和read_users
路徑操作都依賴於這些引數。這種方式避免了程式碼重複,並提高了可維護性。
中介層(Middleware)
中介層允許我們在請求被路徑操作處理之前或回應被傳送給客戶端之前對其進行修改。
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
import time
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
內容解密:
此中介層計算了處理請求所需的時間,並將其新增到回應頭中。這對於監控和除錯非常有用。
CORS(跨來源資源分享)
CORS是一種安全功能,瀏覽器會根據伺服器的組態決定是否允許網頁從不同的來源請求資源。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
內容解密:
此範例組態了CORS中介層,允許來自http://localhost:3000
的請求存取我們的API。這對於開發前端應用程式與後端API分離的架構非常有用。