Reputation: 5152
Let's consider the following example from the documentation:
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 asyncio.sleep(1)
f *= i
print("Task %s: factorial(%s) = %s" % (name, number, f))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
factorial("A", 2),
factorial("B", 3),
factorial("C", 4),
))
loop.close()
The gather function is presented as such in the module:
asyncio.gather(*coros_or_futures, loop=None, return_exceptions=False)
It works all fine, but for my real life problem I need to pass in the gather function not a multiplicity of functions with hardcoded arguments, but rather a tuple comprehension of some form creating the multiple functions.
I tried:
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(
[factorial(str(g),g) for g in range(3)]
))
loop.close()
but it doesnt work. Anyone knows how to have that gather function to work with a programatically created list of functions?
TO BE CLEAR: the gather
function is not defined by me so i cannot remove the * from its definition and simply pass the list of arguments like that. I would need to "unpack" the list but i don't know how.
Upvotes: 6
Views: 17907
Reputation: 1028
List of coroutines can be dynamically generated and passed as follows:
import asyncio
async def factorial(name, number):
f = 1
for i in range(2, number + 1):
print(f"Task {name}: Compute factorial({i})...")
await asyncio.sleep(1)
f *= i
print(f"Task {name}: factorial({number}) = {f}")
async def main():
a = factorial("A", 2)
b = factorial("B", 3)
c = factorial("C", 4)
#
# example passing in list of coroutines
#
await asyncio.gather(*[a,b,c])
asyncio.run(main())
Upvotes: 2
Reputation: 9836
You also can use the itertools.starmap
for this task:
import asyncio
import itertools
async def factorial(name, number):
f = 1
for i in range(2, number+1):
print("Task %s: Compute factorial(%s)..." % (name, i))
await asyncio.sleep(1)
f *= i
print("Task %s: factorial(%s) = %s" % (name, number, f))
loop = asyncio.get_event_loop()
args = [(str(g), g) for g in range(3)]
tasks = itertools.starmap(factorial, args)
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
Make an iterator that computes the function using arguments obtained from the iterable. Used instead of map() when argument parameters are already grouped in tuples from a single iterable (the data has been “pre-zipped”).
For more reading: here
Upvotes: 5
Reputation: 5152
Found the solution:
loop.run_until_complete(asyncio.gather(*(factorial(str(g),g) for g in range(3)))
Upvotes: 5