title: Difference between coroutine and future/task in Python 3.5?
body: <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>