我們在「【🔒 Python API框架篇 - FastAPI】Ep.1 啟航」有分享 FastAPI 這套API框架, 那麼當我們想要在應用程式剛執行時就註冊一些事件或者共享GPU運算模型、變數…等,當整個應用程式關閉時也進行釋放作業, 這樣的一個週期循環就是所謂的生命週期, 而在FastAPI這套框架中也設計了生命週期的管理機制讓我們開發起來更加容易, 就讓我們來看看這是怎麼一回事吧!
假設我們設計一個AI辨識引擎的API, 那麼我們總不希望每次的請求都重新載入模型之後才開始作業吧! 這會非常的耗時, 使用者體驗也非常的糟糕, 我們應該是在程式啟動時就先載好模型, 之後都是等待使用者的請求之後立即就能夠進行作業, 就像是餐廳不可能當每位顧客點餐時才開始備料吧! 這肯定會讓生意非常的糟糕, 千萬不要這樣啊~~~
相信我們應該常常使用以下的程式碼來開啟文字檔吧…
with open('xxx.txt', 'w', encoding='utf-8') as f:
print(...)
它讓我們將釋放資源的作業變得更加簡單, 我們在 with 裡任意進行作業, 也不用特別的去關閉或者釋放檔案的資源, 因為當with裡的作業結束之後就會自動觸發close事件, 看到這裡, 您可能會困惑, 這跟 contextmanager 有啥關係? 其實兩者觀念相似, 主要的目的都是為了省去我們釋放的程序, 一律自動管理, 避免人為疏失導致程式BUG。
在FastAPI裡面有個重要的功能, 那便是「@asynccontextmanager」, 透過它可以定義一個「lifespan」的函式, 定義好開始邏輯之後, 再透過 yield返回, 再定義結束的邏輯如下:
from contextlib import asynccontextmanager
from fastapi import FastAPI
def fake_answer_to_everything_ml_model(x: float):
return x * 42
ml_models = {}
@asynccontextmanager
async def lifespan(app: FastAPI):
# 載入ML模型
ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
yield
# 釋放資源
ml_models.clear()
app = FastAPI(lifespan=lifespan)
@app.get("/predict")
async def predict(x: float):
result = ml_models["answer_to_everything"](x)
return {"result": result}
在FastAPI有個Sharing State可以幫助我們共享狀態, 詳細請參考「【Python 軍火庫🧨 - FastAPI】Sharing State讓路由共享資訊」, 透過共享物件的傳遞, 讓我們節省資源, 達到共用之效果。
我們在設計一個應用程式時,需要做一個全面的考量,在哪些生命週期該做哪些事情這些都需要去思考,FastAPI 對於這些事情基本上支援的很全面,如果官方文件沒有提到,那可以去看他的底層 Starlette 這個框架的官方文件,通常可以獲得你想要的答案。