[Python-ideas] concurrency-local namespaces

Nathaniel Smith njs at pobox.com
Wed Apr 22 07:36:34 CEST 2015


On Tue, Apr 21, 2015 at 4:48 PM, Eric Snow <ericsnowcurrently at gmail.com> wrote:
> threading.local provides thread-local namespaces.  As far as I can
> tell, there isn't an equivalent for coroutines (asyncio), even though
> I would expect they would provide the same benefits.  I'd like to see
> coroutine-local namespaces added and would be happy to work on the
> problem.  I plan on working on a feature that will rely on applying a
> thread-local context and realized that coroutines would need a similar
> treatment.  Also, there are probably a few spots in the stdlib that
> would benefit (e.g. decimal contexts).

Possibly this is off-topic for this thread but -- it's a good point
that, currently, when implementing a global state variable (like the
decimal context), one can bind it to a single thread by storing the
state in TLS, but AFAIK there's no way to do this with coroutines.
It's somewhat unpleasant that

  with decimal.localcontext() as ctx:
      ctx.prec = 10
      values = (yield from db.fetchstuff())
      morecodehere()

can cause arbitrary other code to run with the given decimal context
in effect, while also failing to guarantee that morecodehere() will
run with any particular decimal context.

I hoped for a second that "async with" might help with this, but
checking the PEP it doesn't -- to do that it would need support
context manager callbacks that were called whenever the coroutine got
suspended/resumed while the 'with' block was in effect, but that's not
what it does, it just allows the __enter__ and __exit__ methods
themselves to be coroutines.

And AFAICT the thread Guido linked
(https://github.com/python/asyncio/issues/165) only considers cases
where an async framework (e.g. a web server framework) is the one who
wants to set global variables that can be accessed from within a set
of coroutines. This works out, b/c when the same code controls both
the spawning of coroutines (by creating a new Task) and setting the
variables, so it can bind them together. But that doesn't seem to help
for something like the decimal module context, or numpy's error
handling context
(http://docs.scipy.org/doc/numpy/reference/generated/numpy.errstate.html).

Obviously one can just document that users should always bracket any
yield/await calls with explicit state setting/restore functions, but
is there any better solution?

-n

-- 
Nathaniel J. Smith -- http://vorpus.org


More information about the Python-ideas mailing list