본문 바로가기

Python/FastAPI

[FastAPI] LifeSpan Events에 대해 알아보자



이 글은 FastAPI 프로세스가 시작 또는 종료 될 때, 특정 함수를 호출하는 생명주기 이벤트 핸들링에 대해 정리한다. 내용은 이전에 사용하던 on_event 방식을 먼저 설명하고, 현재 권장하는 lifespan 방식을 설명하는 순서로 진행한다.

1. on_event 방식 (Deprecated)

과거에 FastAPI에서 생명주기 이벤트 핸들링을 할 때는 on_event(with startup and shutdown )를 사용해서 이벤트를 관리했었다.

startup 이벤트를 함수에 선언해서 어플리케이션이 시작하기 전에 실행하도록 한다.
여러 개의 이벤트 함수를 생성할 수도 있으며, 어플리케이션은 모든 startup 이벤트 핸들러가 성공할 때까지 request 수신을 시작할 수 없다.

from fastapi import FastAPI

app = FastAPI()

items = {}

# 어플리케이션이 시작하면 dict 데이터 초기화
@app.on_event("startup")
async def startup_event():
    items["foo"] = {"name": "Fighters"}
    items["bar"] = {"name": "Tenders"}

# 어플리케이션이 끝나면 텍스트를 log.txt 파일에 입력
@app.on_event("shutdown") 
def shutdown_event(): 
    with open("log.txt", mode="a") as log: 
        log.write("Application shutdown")


@app.get("/items/{item_id}")
async def read_items(item_id: str):
    return items[item_id]

FastAPI에 LifeSpan 파라미터를 사용하게 되면, startupshutdown 이벤트 핸들러들이 더이상 호출되지 않는다. LifeSpan과 on_event 방식은 동시에 사용할 수 없다.
async def 혹은 def와 같이 쓸 수 있다.

2. LifeSpan

현재 공식문서에서 권장하는 방법은 FastAPI에서 LifeSpan 파라미터를 사용하는 방식이다.

FastAPI App 인스턴스 생성 시, lifespan 인자를 정의한다.
yield 문을 기준으로 앞에 오는 코드는 어플리케이션 시작 시, 실행하는 코드이고, 뒤에 오는 코드는 서비스 종료 시, 호출된다.

you can define this start up and shutdown logic using the lifespan parameter of the fastAPI app, and a "context manager"

 

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):
    # Load the ML model
    ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
    yield 
    # Clean up the ML models and release the resources
    ml_models.clear()


app = FastAPI(lifespan=lifespan) # app 인스턴스 생성 시, lifespan을 전달


@app.get("/predict")
async def predict(x: float):
    result = ml_models["answer_to_everything"](x)
    return {"result": result}

 

 

 

위 코드는 요청이 처리되기 전에 모델을 로드하되, 코드가 로드되는 동안이 아니라 애플리케이션이 요청을 받기 시작하기 직전에만 로드한다.

@asynccontextmanager
context manager를 사용하면, with block에 들어가기 전에 코드를 실행할 수 있다.
또한, with 문을 벗어나면 yield 문 이후에 코드를 실행할 수도 있다.

🚨 Tip

Keep in mind that these lifespan events (startup and shutdown) will only be executed for the main application, not for Sub Applications - Mounts.


Lifespan Protocol

FastAPI는 Starlette 기반의 비동기 엔진이기 때문에 Starlette의 LifeSpan Handlers 공식 문서를 보는 도 도움이 된다. Starlette's Lifespan' docs.