Difference between coroutine and future/task in Python 3.5?
<p>Let's say we have a dummy function:</p>
<pre><code>async def foo(arg):
    result = await some_remote_call(arg)
    return result.upper()
</code></pre>
<p>What's the difference between:</p>
<pre><code>import asyncio    

coros = []
for i in range(5):
    coros.append(foo(i))

loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait(coros))
</code></pre>
<p>And:</p>
<pre><code>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))
</code></pre>
<p><em>Note</em>: The example returns a result, but this isn't the focus of the question. When return value matters, use <code>gather()</code> instead of <code>wait()</code>.</p>
<p>Regardless of return value, I'm looking for clarity on <code>ensure_future()</code>. <code>wait(coros)</code> and <code>wait(futures)</code> both run the coroutines, so when and why should a coroutine be wrapped in <code>ensure_future</code>?</p>
<p>Basically, what's the Right Way (tm) to run a bunch of non-blocking operations using Python 3.5's <code>async</code>?</p>
<p>For extra credit, what if I want to batch the calls? For example, I need to call <code>some_remote_call(...)</code> 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 <code>asyncio</code>?</p>
<p><strong>2020 update (Python 3.7+)</strong>: Don't use these snippets. Instead use:</p>
<pre><code>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)
</code></pre>
<p>Also consider using <a href="https://trio.readthedocs.io/" rel="noreferrer">Trio</a>, a robust 3rd party alternative to asyncio.</p>