[Python-Dev] PEP 550 v4: coroutine policy
Antoine Pitrou
solipsis at pitrou.net
Tue Aug 29 14:40:21 EDT 2017
On Mon, 28 Aug 2017 17:24:29 -0400
Yury Selivanov <yselivanov.ml at gmail.com> wrote:
> Long story short, I think we need to rollback our last decision to
> prohibit context propagation up the call stack in coroutines. In PEP
> 550 v3 and earlier, the following snippet would work just fine:
>
> var = new_context_var()
>
> async def bar():
> var.set(42)
>
> async def foo():
> await bar()
> assert var.get() == 42 # with previous PEP 550 semantics
>
> run_until_complete(foo())
>
> But it would break if a user wrapped "await bar()" with "wait_for()":
>
> var = new_context_var()
>
> async def bar():
> var.set(42)
>
> async def foo():
> await wait_for(bar(), 1)
> assert var.get() == 42 # AssertionError !!!
>
> run_until_complete(foo())
>
[...]
> So I guess we have no other choice other than reverting this spec
> change for coroutines. The very first example in this email should
> start working again.
What about the second one? Why wouldn't the bar() coroutine inherit
the LC at the point it's instantiated (i.e. where the synchronous bar()
call is done)?
> This means that PEP 550 will have a caveat for async code: don't rely
> on context propagation up the call stack, unless you are writing
> __aenter__ and __aexit__ that are guaranteed to be called without
> being wrapped into a Task.
Hmm, sorry for being a bit slow, but I'm not sure what this
sentence implies. How is the user supposed to know whether something
will be wrapped into a Task (short of being an expert in asyncio
internals perhaps)?
Actually, if could whip up an example of what you mean here, it would
be helpful I think :-)
> Thus I propose to stop associating PEP 550 concepts with
> (dynamic) scoping.
Agreed that dynamic scoping is a red herring here.
Regards
Antoine.
More information about the Python-Dev
mailing list