[Python-ideas] awaiting iterables

Ron Adam ron3200 at gmail.com
Sat May 2 20:12:51 CEST 2015


(I had posted this in the "more general 'for' loop" thread, but this really 
is a different idea from that.)

Initialising several coroutines at once still doesn't seem clear/clean to me.

Here is what I would like.

values = awaiting [awaitable, awaitable, ...]
a, b, ... = awaiting (awaitable, awaitable, ...)

This doesn't have the issues of order because a list of values is returned 
with the same order of the awaitables.  But the awaitables are scheduled in 
parallel.

A regular for loop could still do these in order, but would pause when it 
gets to a values that hasn't returned/resolved yet.  That would probably be 
expected.

     for x in awaiting [awaitable, awaitable, ...]:
         print(x)

X is printed in the order of the awaitables.


Awaiting sets would be different... they are unordered.  So we could use a 
set and get the items that become available as they become available...

     for x in awaiting {awaitable, awaitable, ...}:
         print(x)

x would print in an arbitrary order, but that would be what I would expect 
here.

The body could have await calls in it, and so it could cooperate along with 
the awaiting set of awaitablers.  Of course if the for body is only a few 
statements, that probably wouldn't make much difference.

This seems like it's both explicit and simple to think about.  It also 
seems like it might not be that hard to do, I think most of the parts are 
already worked out.

One option is to allow await to work with iterables in this way.  But the 
awaiting keyword would make the code clearer and error messages nicer.

The last piece of the puzzle is how to specify the current coroutine 
manager/runner.

    import asyncio
    with asyncio.coroutine_loop():
        main()

That seems simple enough.  It prettty much abstracts out all the coroutine 
specific stuff to three keyword.  async, await, and awaiting.

Are async for and async with needed if we have awaiting?  Can they be 
impelented in terms of awaiting?


import asyncio

async def factorial(name, number):
     f = 1
     for i in range(2, number+1):
         print("Task %s: Compute factorial(%s)..." % (name, i))
         await yielding()
         f *= i
     print("Task %s: factorial(%s) = %s" % (name, number, f))

with asyncio.coroutine_loop():
     awaiting [
         factorial("A", 2),
         factorial("B", 3),
         factorial("C", 4)]


Compared to the example in asyncio docs...


import asyncio

@asyncio.coroutine
def factorial(name, number):
     f = 1
     for i in range(2, number+1):
         print("Task %s: Compute factorial(%s)..." % (name, i))
         yield from asyncio.sleep(1)
         f *= i
     print("Task %s: factorial(%s) = %s" % (name, number, f))

loop = asyncio.get_event_loop()
tasks = [
     asyncio.async(factorial("A", 2)),
     asyncio.async(factorial("B", 3)),
     asyncio.async(factorial("C", 4))]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()



Cheers,
    Ron



More information about the Python-ideas mailing list