pythonfastapilifecyclestarlette

Add startup/shutdown handlers to FastAPI app with lifespan API


Consider a FastAPI using the lifespan parameter like this:

def lifespan(app):
    print('lifespan start')
    yield
    print('lifespan end')


app = FastAPI(lifespan=lifespan)

Now I want to register a sub app with its own lifecycle functions:

app.mount(mount_path, sub_app)

How can I register startup/shutdown handlers for the sub app?

All solutions I could find either require control over the lifespan generator (which I don't have) or involve deprecated methods like add_event_handler (which doesn't work when lifespan is set).


Update Minimal reproducible example:

from fastapi import FastAPI

# --- main app ---

def lifespan(_):
    print("startup")
    yield
    print("shutdown")

app = FastAPI(lifespan=lifespan)

@app.get("/")
async def root():
    return {"message": "Hello World"}

# --- sub app ---

sub_app = FastAPI()

@sub_app.get("/")
async def sub_root():
    return {"message": "Hello Sub World"}

app.mount("/sub", sub_app)
app.on_event("startup")(lambda: print("sub startup"))    # doesn't work
app.on_event("shutdown")(lambda: print("sub shutdown"))  # doesn't work

Run with: uvicorn my_app:app --port 8000


Solution

  • I found a solution, but I'm not sure if I like it... It accesses the existing lifespan generator via app.router.lifespan_context and wraps it with additional startup/shutdown commands:

    from contextlib import asynccontextmanager
    
    ...
    
    main_app_lifespan = app.router.lifespan_context
    
    @asynccontextmanager
    async def lifespan_wrapper(app):
        print("sub startup")
        async with main_app_lifespan(app) as maybe_state:
            yield maybe_state
        print("sub shutdown")
    
    app.router.lifespan_context = lifespan_wrapper
    

    Output:

    INFO:     Waiting for application startup.
    sub startup
    startup
    INFO:     Application startup complete.
    ...
    INFO:     Shutting down
    INFO:     Waiting for application shutdown.
    shutdown
    sub shutdown
    INFO:     Application shutdown complete.