Skip to content

bpo-40320: Added support for manipulating context in asyncio tasks #26664

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

msg555
Copy link

@msg555 msg555 commented Jun 11, 2021

Proposal and sample implementation to address https://bugs.python.org/issue40320 and extend behavior a bit to get parity with what's available in synchronous code.

Makes three public API changes

  1. Adds a context keyword parameter to the asyncio.Task constructor. When given this will be the contextvars.Context the task will be run in. When not specified the existing default of copying the callers context will still be used.
  2. Updates asyncio.run to pass additional keyword arguments to the task constructor. This isn't really necessary but seemed like a nice (and it also seemed like it would be nice if you could specify the name of the task created by asyncio.run).
  3. Created coroutine asyncio.run_in_context that functions in an analagous manner to contextvars.Context.run. It will manage swapping out the coroutine associated with the task while the passed coroutine is executing within the task.

asyncio.run_in_context is implemented by assing an additional private method Task._set_context that can change the context associated with a task (although a yield out of the task step function is required before the new context is active).

This is all to better support contextvars in an asyncio context. Without this support it was impossible to run async code in a different context without creating a new task. It was also impossible to create a task using any context other than a copy of the calling context (i.e. the context used was always a copy).

Example Usage

import asyncio
import contextvars

var = contextvars.ContextVar("var", default=123)

async def foo():
  val = var.get()
  var.set(val + 1)
  return val

async def main():
  assert await foo() == 123
  assert await asyncio.run_in_context(contextvars.copy_context(), foo()) == 124
  assert var.get() == 124

var.set(-1)
ctx = contextvars.Context()
asyncio.run(main(), name='main', context=ctx)

https://bugs.python.org/issue40320

Signed-off-by: Mark Gordon <msg555@gmail.com>
@msg555 msg555 requested review from 1st1 and asvetlov as code owners June 11, 2021 06:34
@msg555 msg555 changed the title bp-40320: Added support for manipulating context in asyncio tasks bpo-40320: Added support for manipulating context in asyncio tasks Jun 11, 2021
@github-actions
Copy link

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions bot added the stale Stale PR or inactive for long period of time. label Jul 12, 2021
@msg555 msg555 closed this Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review stale Stale PR or inactive for long period of time.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants