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

Nick Coghlan ncoghlan at gmail.com
Tue Aug 29 08:21:56 EDT 2017


On 29 August 2017 at 07:24, Yury Selivanov <yselivanov.ml at gmail.com> wrote:

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.

I'm not sure if it was Nathaniel or Stefan that raised it, but I liked the analogy that compared wrapping a coroutine in a new Task to submitting a synchronous function call to a concurrent.futures executor: while the dispatch layer is able to pass down a snapshot of the current execution context to the submitted function or wrapped coroutine, the potential for concurrent execution of multiple activities using that same context means the dispatcher can't reliably pass back any changes that the child context makes.

For example, consider the following:

def func():
    with make_executor() as executor:
        fut1 = executor.submit(other_func1)
        fut2 = executor.submit(other_func2)
        result1 = fut1.result()
        result2 = fut2.result()

async def coro():
    fut1 = asyncio.ensure_future(other_coro1())
    fut2 = asyncio.ensure_future(other_coro2())
    result1 = await fut1
    result2 = await fut2

For both of these cases, it shouldn't matter which order we use to wait for the results, or if we perform any other operations in between, and the only way to be sure of that outcome is if the dispatch operations (whether that's asyncio.ensure_future or executor.submit) prevent reverse propagation of context changes from the operation being dispatched.

Cheers, Nick.

-- Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia



More information about the Python-Dev mailing list