The lifespan context manager helps you run setup and cleanup code when your FastAPI app starts and stops. It keeps your app organized and efficient.
Lifespan context manager in FastAPI
Start learning this pattern below
Jump into concepts and practice - no test required
from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): # setup code here yield # cleanup code here app = FastAPI(lifespan=lifespan)
The @asynccontextmanager decorator marks the function as a lifespan manager.
The code before yield runs at startup, and the code after yield runs at shutdown.
from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): print('Starting app') yield print('Stopping app') app = FastAPI(lifespan=lifespan)
from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): app.state.db = connect_to_db() yield app.state.db.disconnect()
This FastAPI app uses the lifespan context manager to print messages when starting and stopping. It also keeps a counter of visits stored in app.state. Each time you visit the root URL, the counter increases.
from fastapi import FastAPI from contextlib import asynccontextmanager @asynccontextmanager async def lifespan(app: FastAPI): print('App is starting') app.state.counter = 0 yield print('App is stopping') app = FastAPI(lifespan=lifespan) @app.get('/') async def read_root(): app.state.counter += 1 return {"visits": app.state.counter}
Use app.state to store data you want to keep during the app's life.
The lifespan function must be async and use yield to separate startup and shutdown code.
FastAPI automatically calls the lifespan manager when the app runs with an ASGI server like Uvicorn.
The lifespan context manager runs code when your FastAPI app starts and stops.
Use it to set up and clean up resources like databases or background tasks.
It keeps your app organized and efficient by managing app-wide state.
Practice
lifespan context manager in a FastAPI application?Solution
Step 1: Understand the role of lifespan context manager
The lifespan context manager is designed to run code at the start and end of the FastAPI app lifecycle.Step 2: Identify its main use
It is used to set up resources like database connections when the app starts and clean them up when the app stops.Final Answer:
To run setup code when the app starts and cleanup code when it stops -> Option DQuick Check:
Lifespan manages startup and shutdown code = A [OK]
- Confusing lifespan with route handling
- Thinking lifespan manages HTTP requests
- Assuming lifespan handles user sessions
Solution
Step 1: Recall lifespan signature
The lifespan function must be async and accept the app parameter to manage startup and shutdown.Step 2: Confirm use of yield
Usingyieldinside the async function allows running code before and after the yield for startup and shutdown.Final Answer:
async def lifespan(app): yield -> Option AQuick Check:
Async + app param + yield = A [OK]
- Forgetting async keyword
- Missing app parameter
- Using return instead of yield
async def lifespan(app):
print('Starting app')
yield
print('Stopping app')Solution
Step 1: Understand yield in lifespan
The code beforeyieldruns at startup, and code afteryieldruns at shutdown.Step 2: Match prints to lifecycle events
So 'Starting app' prints when app starts, and 'Stopping app' prints when app stops.Final Answer:
'Starting app' prints on start, 'Stopping app' prints on shutdown -> Option BQuick Check:
Code before yield = start, after yield = stop [OK]
- Thinking both prints run immediately
- Assuming yield blocks all prints
- Confusing start and stop timing
async def lifespan(app):
print('Starting')
return
print('Stopping')Solution
Step 1: Identify use of return instead of yield
The lifespan function must useyieldto separate startup and shutdown code.Step 2: Understand effect of return
Usingreturnexits the function immediately, so shutdown code after it never runs.Final Answer:
Using return instead of yield prevents shutdown code from running -> Option CQuick Check:
Return exits early; yield separates start/stop [OK]
- Confusing return and yield in async functions
- Ignoring that shutdown code runs after yield
- Assuming print statements cause errors
Solution
Step 1: Confirm async function with app parameter
The lifespan function must be async and accept the app parameter to store the db connection.Step 2: Check order of operations
Connect to the database before yield, store it on app.state, then close it after yield.Step 3: Verify correct use of await and yield
Await connect_db and db.close, yield separates startup and shutdown code.Final Answer:
async def lifespan(app): db = await connect_db() app.state.db = db yield await db.close() -> Option AQuick Check:
Async + app param + yield + await connect/close = D [OK]
- Placing yield before storing db connection
- Missing async or await keywords
- Not passing app parameter to lifespan
