[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