Questions tagged [python-contextvars]

Contextvars are a concept similar to thread-local variables, intended to provide value isolation across co-routines executed in parallel in a Python async application. They are implemented in a module with the same name introduced in the stdlib in Python 3.7.0, specified in PEP-567.

Python-contextvars were first justified and introduced in PEP-550, which ended-up being rejected mainly for holding a too-ambitious scope. A narrowed down proposal came in PEP-567 that ended up implemented in Python 3.7.0. The idea is to be able to have cross-local scope values that can be shared across co-routines running in the same task under async-io, in the same way that thread-local-storage variables can provide value isolation for variable-names across different threads.

PEP 550 presents context vars as:

This PEP adds a new generic mechanism of ensuring consistent access to non-local state in the context of out-of-order execution, such as in Python generators and coroutines.

Thread-local storage, such as threading.local(), is inadequate for programs that execute concurrently in the same OS thread. This PEP proposes a solution to this problem.

34 questions
21
votes
1 answer

Understanding Python contextvars

Regarding the following SO answer . I've made some changes in order to understand the difference between do use Contextvars and don't. I expect at some point the variable myid gets corrupted but changing the range to a higher number seems doesn't…
Ricardo
  • 7,921
  • 14
  • 64
  • 111
16
votes
4 answers

ContextVars across modules

I am completely newb on asyncio and ContextVars, I just read up what's new in 3.7 and discovered ContextVars, I struggle to understand it's usage, all I know it's helpful in coroutines, instead of using thread.local should use ContextVars. But none…
James Lin
  • 25,028
  • 36
  • 133
  • 233
10
votes
1 answer

Is there any reason to use Python threading.local() rather than a ContextVar (in >= 3.7)

Python's thread-local data and ContextVars appear to achieve the same thing (while having slightly different APIs), with the only user-facing difference being that ContextVars work with async code (coroutines and asyncio), while thread-local data…
Graham Lea
  • 5,797
  • 3
  • 40
  • 55
8
votes
2 answers

What happens if I don't reset Python's ContextVars?

Is this a memory leak in Python? import contextvars contextvar = contextvars.ContextVar('example') while True: string = 'hello world' token = contextvar.set(string) Is a contextvar a stack that keeps on growing the more you push to it? What…
Rol
  • 501
  • 4
  • 13
5
votes
2 answers

Factory for contextvar default value

Setting a dictionary as ContextVar default: var: ContextVar[dict] = ContextVar('var', default={}) ...kinda works, as the dictionary will be available as default, but it always references the same instance, instead of generating a new one for each…
Tuukka Mustonen
  • 4,722
  • 9
  • 49
  • 79
5
votes
1 answer

How to run a coroutine inside a context?

In the Python docs about Context Vars a Context::run method is described to enable executing a callable inside a context so changes that the callable perform to the context are contained inside the copied Context. Though what if you need to execute…
5
votes
0 answers

Fetching Context Variables by identifier

I'm trying to use the new contextvars library (https://docs.python.org/3/library/contextvars.html) to make certain values available across modules in an async context, similar to ContextVars across modules, and was wondering if there was a way of…
vogelier
  • 51
  • 1
5
votes
1 answer

How do I write consistent stateful context managers?

EDIT: As pointed out by Thierry Lathuille, PEP567, where ContextVar was introduced, was not designed to address generators (unlike the withdrawn PEP550). Still, the main question remains. How do I write stateful context managers that behave…
jdehesa
  • 58,456
  • 7
  • 77
  • 121
4
votes
1 answer

Will a ContextVar leak memory in async logic if not reset after Exception?

If I have a structure in an async webserver like import contextvars ... my_context_var = contextvars.ContextVar("var") @app.route("/foo") # decorator from webserver async def some_web_endpoint(): local_ctx_var =…
ti7
  • 16,375
  • 6
  • 40
  • 68
4
votes
1 answer

Provide contextvars.Context with a ContextManager

I'm trying to manage transactions in my DB framework (I use MongoDB with umongo over pymongo). To use transaction, one must pass a session kwarg along the whole call chain. I would like to provide a context manager that would isolate the…
Jérôme
  • 13,328
  • 7
  • 56
  • 106
3
votes
0 answers

Subclass python ContextVar

Is there a legal pythonic way to store one additional attribute in ContextVar? I can't subclass ContextVar because of TypeError I can from contextvars import ContextVar as BaseContextVar class ContextVar: def __init__(self, name, *,…
Belegnar
  • 721
  • 10
  • 24
2
votes
1 answer

Python: Copy context (contextvars.Context) to a separate thread

As for now, I've found a lot of examples on how contextvars module behaves with asyncio, but none on how one behaves with threads (asyncio.get_event_loop().run_in_executor, threading.Thread, and so on). My question is, how can I pass context to a…
2
votes
1 answer

How can i deal with context var in asyncio while it is in a 'while' cycle?

Contextvar 'value' doest change as it goes through 'while' cycle . ''' import contextvars import keyboard import asyncio import random value = contextvars.ContextVar('value') value.set('-') async def q(): while True: await…
wasjusty
  • 21
  • 2
2
votes
2 answers

Copying contexvars.Context between tasks

I have a program (an ASGI server) that is structured roughly like this: import asyncio import contextvars ctxvar = contextvars.ContextVar("ctx") async def lifepsan(): ctxvar.set("spam") async def endpoint(): assert ctxvar.get() ==…
LoveToCode
  • 788
  • 6
  • 14
2
votes
2 answers

Access to contextvars in asyncio add_done_callback callback

In Python async function I'am creating ContextVar, task and attaching callback to it: bbb = contextvars.ContextVar('aaa') bbb.set(3) task = self.loop.create_task(self.someFunc()) task.add_done_callback(self.commonCallback) bbb.set(4) In callback I…
1
2 3