FastAPI 的效能優勢源於其非同步程式設計模型和 Starlette 的高效能網路核心,使其能處理大量並發請求。內建的 Swagger UI 自動生成互動式 API 檔案,簡化開發流程。除了 RESTful API,FastAPI 也支援 WebSockets 和 GraphQL,提供更靈活的資料交換方式。型別提示的運用強化了程式碼可讀性和維護性,同時也減少了執行時期錯誤的風險。此外,FastAPI 提供了 OAuth2 和 JWT 等安全機制,並方便整合測試工具,確保應用程式的穩定性和安全性。最後,FastAPI 支援多種佈署方式,包含 Docker 容器和雲端平台,方便開發者快速上線應用服務。

深入理解FastAPI:建構現代化Python後端服務

FastAPI是一個現代化的Python Web框架,專為建構高效能且可擴充套件的API而設計。它結合了快速開發、強大的型別檢查和自動化的檔案生成,使其成為開發人員的首選框架之一。本文將探討FastAPI的核心功能、優勢以及如何利用它來建構強大的後端服務。

FastAPI的核心功能

1. 非同步程式設計

FastAPI全面支援非同步程式設計,這使得它能夠處理大量並發請求而不會阻塞主執行緒。這對於需要處理即時資料或高並發請求的應用程式來說至關重要。

from fastapi import FastAPI
import asyncio

app = FastAPI()

async def fetch_data():
    await asyncio.sleep(1)
    return {"data": "Fetched data"}

@app.get("/data")
async def read_data():
    data = await fetch_data()
    return data

內容解密:

這段程式碼展示瞭如何在FastAPI中使用非同步函式。fetch_data函式模擬了一個非同步操作,例如從資料函式庫或外部API取得資料。read_data端點呼叫這個非同步函式並傳回結果。

2. 自動檔案生成

FastAPI能夠根據你的程式碼自動生成互動式API檔案。這不僅節省了手動編寫檔案的時間,還確保了檔案的準確性和即時性。

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

內容解密:

這段程式碼定義了一個簡單的端點,當存取/items/{item_id}時,它會傳回一個包含item_id的JSON物件。FastAPI會自動為這個端點生成檔案,包括引數說明和範例請求。

3. 強大的型別檢查

FastAPI利用Python的型別提示來進行強大的型別檢查和驗證。這不僅提高了程式碼的可讀性,還減少了執行階段錯誤的可能性。

from pydantic import BaseModel
from fastapi import FastAPI

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool = None

@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item):
    return {"item_name": item.name, "item_id": item_id}

內容解密:

這段程式碼定義了一個Item模型,用於驗證傳入的JSON資料。update_item端點使用這個模型來確保請求體的正確性,並傳回更新後的專案資訊。

WebSockets支援

FastAPI提供了對WebSockets的原生支援,使得實作即時雙向通訊變得簡單。這對於需要即時更新的應用程式(如聊天應用或即時資料分析)非常有用。

from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Message text was: {data}")

內容解密:

這段程式碼建立了一個WebSocket端點。當客戶端連線時,伺服器會接受連線並進入一個無限迴圈,接收客戶端傳送的訊息並回傳確認訊息。

GraphQL整合

FastAPI可以與GraphQL整合,提供更靈活的資料查詢方式。這使得客戶端可以精確地請求所需的資料,減少不必要的資料傳輸。

import strawberry
from fastapi import FastAPI
from strawberry.asgi import GraphQL

@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "Hello World"

schema = strawberry.Schema(Query)
graphql_app = GraphQL(schema)

app = FastAPI()
app.add_route("/graphql", graphql_app)
app.add_websocket_route("/graphql", graphql_app)

內容解密:

這段程式碼使用Strawberry函式庫在FastAPI中實作了一個簡單的GraphQL API。它定義了一個Query型別,其中包含一個hello欄位,傳回"Hello World"字串。

安全性與測試

FastAPI提供了多種安全功能,如OAuth2和JWT驗證。同時,它也支援全面的測試,包括對WebSockets和資料函式庫操作的測試。

from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import OAuth2PasswordBearer

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")

app = FastAPI()

async def get_current_user(token: str = Depends(oauth2_scheme)):
    if token != "fake_token":
        raise HTTPException(status_code=401, detail="Invalid authentication credentials")
    return token

@app.get("/users/me")
async def read_users_me(current_user: str = Depends(get_current_user)):
    return {"username": current_user}

內容解密:

這段程式碼實作了一個簡單的OAuth2驗證機制。get_current_user函式用於驗證傳入的token,如果token無效,則傳回401錯誤。read_users_me端點依賴於這個驗證函式來取得當前使用者資訊。

佈署策略

FastAPI應用可以佈署在多種環境中,包括Docker容器、雲端平台如Google Cloud和AWS,以及傳統的WSGI伺服器。

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

內容解密:

這段Dockerfile用於將FastAPI應用容器化。它根據Python 3.9映像,安裝依賴項,複製應用程式碼,並設定使用Uvicorn執行應用。

第一章:FastAPI簡介

近年來,Python作為一門程式語言,其受歡迎程度大幅提升,主要歸因於其在資料科學領域的豐富函式庫。然而,Python同樣被廣泛應用於網頁應用程式開發,這得益於其豐富的網頁應用框架。

FastAPI是Python網頁應用框架的最新成員,但它並非只是另一個框架。FastAPI具備一些明顯的優勢,被認為是最快的框架之一,它充分利用了現代Python的功能。本章將介紹FastAPI函式庫所根據的重要功能。

本章涵蓋以下主題:

  • 型別提示
  • 非同步處理
  • REST架構
  • HTTP動詞
  • FastAPI依賴項
  • FastAPI安裝

型別提示

Python是一種動態型別語言。相反,C/C++和Java等語言是靜態型別語言,在這些語言中,變數的型別必須在指定之前宣告。在C/C++/Java程式的生命週期中,變數只能持有其宣告型別的資料。在Python中,情況恰恰相反。變數的型別由賦給它的值決定,並且可以在每次指定時動態更改。

清單1-1:動態型別

>>> x = 10
>>> # x是一個int變數
>>> x = (1, 2, 3)
>>> type(x)
<class 'tuple'>
>>> x = [1, 2, 3]
>>> # x現在是一個list
>>> type(x)
<class 'list'>
>>> x = "Hello World"
>>> # x現在變成了一個str變數
>>> type(x)
<class 'str'>

內容解密:

在上述範例中,變數x的型別隨著指定不同而改變。初始時x被指定為整數10,隨後被指定為元組(1, 2, 3)、列表[1, 2, 3]和字串"Hello World"。每次指定後,x的型別都發生了變化。

雖然這種動態型別特性使得程式設計更加容易,但也容易遇到執行時錯誤,因為Python直譯器在執行之前不會強制進行任何型別檢查。

清單1-2:Python函式

# hint.py
def division(num, den):
    return num / den

內容解密:

此函式接受兩個引數numden,並傳回它們的除法結果。然而,如果傳入的引數型別不正確,例如將字串傳入,將導致執行時錯誤。

清單1-3:函式中的TypeError

>>> from hint import division
>>> division(10, 2)
5.0
>>> division(10, 2.5)
4.0
>>> division("Python", 2)
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    division("Python", 2)
  File "F:\python36\hint.py", line 3, in division
    return num / den
TypeError: unsupported operand type(s) for /: 'str' and 'int'

內容解密:

前兩次對division()函式的呼叫成功,但第三次呼叫由於嘗試對字串和整數進行除法運算而丟擲了TypeError例外。

標準Python安裝所附帶的預設Python直譯器(Python shell)功能相當基礎。更先進的Python執行環境,如IPython和Jupyter Notebook,以及許多Python IDE(如VS Code、PyCharm,包括隨標準函式庫附帶的基本IDE IDLE),都具有諸如自動完成、語法高亮和型別預測幫助等實用功能。圖1-1展示了IPython的自動完成功能。

IPython自動完成示意圖

  graph LR;
    A[使用者輸入] --> B[IPython直譯器];
    B --> C[自動完成建議];
    C --> D[使用者選擇];
    D --> E[程式碼自動補全];

圖表翻譯: 此圖示展示了IPython的自動完成功能的工作流程。當使用者輸入程式碼時,IPython直譯器會提供自動完成的建議。使用者可以從這些建議中選擇需要的選項,從而實作程式碼的自動補全。

型別提示的重要性

儘管Python是動態型別語言,但型別提示(Type Hints)可以幫助開發者更好地理解函式或方法的預期輸入和輸出型別,從而提高程式碼的可讀性和可維護性。

範例:使用型別提示的函式

def greeting(name: str) -> str:
    return 'Hello ' + name

內容解密:

在這個範例中,greeting函式接受一個字串引數name,並傳回一個字串。這裡使用了型別提示來明確函式的輸入和輸出型別,使得函式的使用更加清晰。

FastAPI依賴項

FastAPI根據Starlette和Pydantic這兩個函式庫。Starlette是一個輕量級的ASGI框架/工具包,非常適合用於建立高效能的非同步服務。Pydantic則是一個執行時型別檢查和驗證的函式庫,用於確保資料模型的正確性。

範例:Pydantic模型定義

from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

內容解密:

在這個範例中,我們定義了一個名為User的Pydantic模型,它具有三個屬性:idnameemail,分別對應整數、字串和字串型別。Pydantic會在執行時檢查賦給這些屬性的值的型別是否正確。

FastAPI安裝

要安裝FastAPI,可以使用pip命令。

pip install fastapi uvicorn

內容解密:

這條命令會安裝FastAPI及其所需的依賴項,以及用於執行ASGI應用的伺服器uvicorn。

隨著現代網頁應用程式對效能要求的提高,FastAPI憑藉其對非同步處理和型別提示的支援,已經成為開發高效能網頁應用的首選框架之一。未來,我們可以預期看到更多根據FastAPI構建的高效能網頁應用。

總之,本章介紹了FastAPI的一些基礎知識,包括型別提示、非同步處理、REST架構、HTTP動詞、FastAPI依賴項和安裝。這些知識為進一步學習和使用FastAPI打下了堅實的基礎。在接下來的章節中,我們將繼續探討FastAPI的其他重要功能和應用場景,以幫助讀者更好地掌握這一強大的網頁應用框架。

Python型別提示(Type Hinting)與非同步處理(Asynchronous Processing)詳解

Python型別提示(Type Hinting)

Python 3.5版本引入了型別提示(Type Hinting)功能,允許開發者在變數宣告、函式引數以及回傳值中指定預期的資料型別。雖然Python直譯器不會強制執行型別檢查,但IDE(整合開發環境)如VS Code可以利用這些提示提供更好的程式碼自動完成、型別檢查以及檔案產生。

型別提示的基本使用

以下是一個簡單的範例,展示如何在函式定義中使用型別提示:

def division(num: int, den: int) -> float:
    return num / den

在上述範例中,numden被指定為int型別,而函式的回傳值則被指定為float型別。

內容解密:

  1. def division(num: int, den: int) -> float::這行程式碼定義了一個名為division的函式,接受兩個整數引數numden,並回傳一個浮點數。
  2. num: intden: int:這兩個引數被指定為整數型別,IDE會根據這些提示提供相關的警告或自動完成建議。
  3. -> float:表示該函式會回傳一個浮點數。

typing模組的進階型別提示

Python的typing模組提供了更多進階的型別提示功能,例如ListTupleDictUnionAny以及Optional等。

from typing import List, Tuple, Union

# 使用List[float]指定列表中元素的型別為浮點數
l2: List[float] = [100, 25.50, 2.2E-2]

# 使用Tuple[Union[int, str]]指定元組中元素可以是整數或字串
l3: Tuple[Union[int, str]] = [5, "Python", 100]

內容解密:

  1. from typing import List, Tuple, Union:匯入typing模組中的進階型別提示類別。
  2. l2: List[float]:宣告一個名為l2的列表變數,並指定其元素應為浮點數型別。
  3. l3: Tuple[Union[int, str]]:宣告一個名為l3的元組變數,並指定其元素可以是整數或字串。

非同步處理(Asynchronous Processing)

Python 3.5版本開始支援非同步處理,非同步處理允許多個任務在單一執行緒中協同工作,提高程式的平行處理能力。

asyncio模組與非同步函式

Python的asyncio模組提供了非同步處理的核心功能,而asyncawait關鍵字則用於定義和呼叫非同步函式。

import asyncio

async def sayhello():
    print("Hello Python")

async def main():
    for _ in range(5):
        await sayhello()

asyncio.run(main())

內容解密:

  1. async def sayhello()::定義一個名為sayhello的非同步函式。
  2. async def main()::定義一個名為main的非同步函式,其中包含一個迴圈呼叫sayhello()
  3. await sayhello():在main()函式中,使用await關鍵字等待sayhello()函式的完成。
  4. asyncio.run(main()):使用asyncio.run()函式執行main()非同步函式。

隨著Python的不斷演進,型別提示和非同步處理將會變得更加完善和強大。未來,我們可以期待更多根據這些功能的框架和工具出現,以進一步簡化Python開發流程並提高程式效能。