Startup and Shutdown¶
The ASGI lifespan specification includes the ability for awaiting
coroutines before the first byte is received and after the final byte
is sent, through the
shutdown lifespan events.
This is particularly useful for creating and destroying connection
pools. Quart supports this via the decorators
after_serving(), which function like
while_serving() which expects a function that
returns a generator.
The decorated functions are all called within the app context,
g to be used.
g with caution, as it will reset after startup, i.e. after
before_serving functions complete and after the
initial yield in a while serving generator. It can still be used
within this context. If you want to create something used in
routes, try storing it on the app instead.
To use this functionality simply do the following:
@app.before_serving async def create_db_pool(): app.db_pool = await ... g.something = something @app.before_serving async def use_g(): g.something.do_something() @app.while_serving async def lifespan(): ... # startup yield ... # shutdown @app.route("/") async def index(): app.db_pool.execute(...) # g.something is not available here @app.after_serving async def create_db_pool(): await app.db_pool.close()
Quart’s test client works on a request lifespan and hence does not
after_serving functions, nor advance
while_serving generator. Instead Quart’s test app can be used,
@pytest.fixture(name="app", scope="function") async def _app(): app = create_app() # Initialize app async with app.test_app() as test_app: yield test_app
The app fixture can then be used as normal, knowing that the
after_serving functions have been called,
while_serving generator has been advanced,
@pytest.mark.asyncio async def test_index(app): test_client = app.test_client() await test_client.get("/") ...