Let's say we have a dummy function:
async def foo(arg):
result = await some_remote_call(arg)
return result.upper()
What's the difference between:
import asyncio
coros = []
for i in range(5):
coros.append(foo(i))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coros))
And:
import asyncio
futures = []
for i in range(5):
futures.append(asyncio.ensure_future(foo(i)))
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(futures))
Note: The example returns a result, but this isn't the focus of the question. When return value matters, use gather()
instead of wait()
.
Regardless of return value, I'm looking for clarity on ensure_future()
. wait(coros)
and wait(futures)
both run the coroutines, so when and why should a coroutine be wrapped in ensure_future
?
Basically, what's the Right Way (tm) to run a bunch of non-blocking operations using Python 3.5's async
?
For extra credit, what if I want to batch the calls? For example, I need to call some_remote_call(...)
1000 times, but I don't want to crush the web server/database/etc with 1000 simultaneous connections. This is doable with a thread or process pool, but is there a way to do this with asyncio
?
2020 update (Python 3.7+): Don't use these snippets. Instead use:
import asyncio
async def do_something_async():
tasks = []
for i in range(5):
tasks.append(asyncio.create_task(foo(i)))
await asyncio.gather(*tasks)
def do_something():
asyncio.run(do_something_async)
Also consider using Trio, a robust 3rd party alternative to asyncio.