Lifespan
yield = startup.from contextlib import asynccontextmanager
@asynccontextmanager
async def lifespan(app):
# STARTUP — runs before first request
await map_client.connect()
yield # ← app runs here, handling requests
# SHUTDOWN — runs after last request
await map_client.close()
app = FastAPI(lifespan=lifespan)
from fastapi import FastAPI, APIRouter, HTTPException
app = FastAPI()
router = APIRouter(prefix="/drones", tags=["drones"])
/routers/drones
{drone_id} — URL parameter, captured from the pathbody: BatteryRequest — FastAPI sees it's a Pydantic model, reads JSON body automaticallyresponse_model=BatteryResult — FastAPI validates and serializes the return value@router.get("/{drone_id}/battery", response_model=BatteryResult)
async def battery(drone_id: str, body: BatteryRequest) -> BatteryResult:
drone = _lookup(drone_id)
return await get_battery_status(drone)
Singleton
dict trick avoids globalglobal).# registry.py
_state: dict[str, Drone | None] = {"drone": None}
def set_drone(drone: Drone) -> None:
_state["drone"] = drone
def get_drone() -> Drone | None:
return _state["drone"]