[Python-Dev] PEP 550 v4 (original) (raw)

Yury Selivanov yselivanov.ml at gmail.com
Wed Aug 30 09:55:59 EDT 2017


On Wed, Aug 30, 2017 at 8:55 AM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:

Yury Selivanov wrote:

BTW we already have mechanisms to always propagate context to the caller -- just use threading.local() or a global variable. But then you don't have a way to not propagate the context change when you don't want to. Here's my suggestion: Make an explicit distinction between creating a new binding for a context var and updating an existing one. So instead of two API calls there would be three: contextvar.new(value) # Creates a new binding only # visible to this frame and # its callees contextvar.set(value) # Updates existing binding in # context inherited from caller contextvar.get() # Retrieves the current binding If we assume an extension to the decimal module so that decimal.localcontext is a context var, we can now do this: async def foo(): # Establish a new context for this task decimal.localcontext.new(decimal.Context()) # Delegate changing the context await bar() # Do some calculations yield 17 * math.pi + 42 async def bar(): # Change context for caller decimal.localcontext.prec = 5

Interesting.

Question: how to write a context manager with contextvar.new?

var = new_context_var()

class CM:

    def __enter__(self):
          var.new(42)

with CM(): print(var.get() or 'None')

My understanding that the above code will print "None", because "var.new()" makes 42 visible only to callees of enter.

But if I use "set()" in "CM.enter", presumably, it will traverse the stack of LCs to the very bottom and set "var=42" in in it. Right?

If so, how can fix the example in PEP 550 Rationale: https://www.python.org/dev/peps/pep-0550/#rationale where we zip() the "fractions()" generator?

With current PEP 550 semantics that's trivial: https://www.python.org/dev/peps/pep-0550/#generators

Yury



More information about the Python-Dev mailing list