Python has the contextvars.copy_context()
function which lets you store a copy of the current values of all the ContextVars
that are currently active. Then later, you can run with all those values active by calling context_returned_by_copy_context.run(func)
. However, the run
method is sync and expects a regular callable, not an async one. How can you run an async function with a context returned by copy_context
?
lord_haffi's suggestion is apropos, but there is no need to create a new event loop since one should already be running:
import asyncio
import contextvars
x = contextvars.ContextVar('x')
async def async_fn():
"""An aysnc coroutine we would like to run with contextvars.Contex.run"""
print(x.get())
def fn():
""" A non-coroutine that we will run with contextvars.Context.run"""
loop = asyncio.get_running_loop()
return loop.create_task(async_fn())
async def demo(value):
x.set(value)
ctx = contextvars.copy_context()
await ctx.run(fn)
async def main():
await asyncio.gather(demo(1), demo(2))
asyncio.run(main())
Prints:
1
2