Setting context variables in the lifespan handler? #2078
-
Hi all, I wonder whether there are any guarantees that context variables which are set in the lifespan handler in a Starlette application are observable in all the HTTP endpoints? I couldn't find it in it the docs. I'd like to use context variables to pass information to the rest of the application. It's also no clear to me whether this depends on Starlette itself, or on the ASGI webserver. (I have a workaround using thread locals, if I have to.) |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
No, it's not possible to set a You'd use the new lifespan state for that. |
Beta Was this translation helpful? Give feedback.
-
Sometimes it's possible to capture top-level context object: def create_app():
ctx = asyncio.current_task().get_context()
return App(..., lifespan=partial(lifespan, ctx)
async def lifespan(top_ctx, app):
top_ctx.run(var.set, value)
... This has some caveats. Each import asyncio
from contextvars import ContextVar
a = ContextVar('a')
a.set(1)
async def task():
print('task before', a.get())
await asyncio.sleep(1)
print('task after', a.get())
async def main():
print('main before', a.get())
t = asyncio.create_task(task())
await asyncio.sleep(0.5)
a.set(2)
print('set(2)')
await asyncio.sleep(1)
print('main after', a.get())
asyncio.run(main()) |
Beta Was this translation helpful? Give feedback.
No, it's not possible to set a
ContextVar
on the lifespan, and to retrieve that value on the endpoint. It's not a limitation, it's just that by concept it doesn't make sense. The lifespan and the request-response cycle run in different tasks.You'd use the new lifespan state for that.