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 startup and shutdown lifespan events. This is particularly useful for creating and destroying connection pools. Quart supports this via the decorators before_serving() and after_serving(), which function like before_first_request().
startup
shutdown
before_serving()
after_serving()
before_first_request()
The decorated functions are all called within the app context, allowing current_app and g to be used.
current_app
g
Warning
Use g with caution, as it will reset after all the before_serving functions complete. It can still be used within this context. If you want to create something used in routes, try storing it on the app instead.
before_serving
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.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 call before_serving or after_serving functions. Instead Quart’s test app can be used, for example
after_serving
@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 before_serving and after_serving functions have been called,
@pytest.mark.asyncio async def test_index(app): test_client = app.test_client() await test_client.get("/") ...