title: How to properly create and run concurrent tasks using python's asyncio module?
body: <p>I am trying to properly understand and implement two concurrently running <a href="https://docs.python.org/3/library/asyncio-task.html#task" rel="nofollow noreferrer"><code>Task</code></a> objects using Python 3's relatively new <a href="https://docs.python.org/3/library/asyncio.html" rel="nofollow noreferrer"><code>asyncio</code></a> module.</p>
  <p>In a nutshell, asyncio seems designed to handle asynchronous processes and concurrent <code>Task</code> execution over an event loop. It promotes the use of <code>await</code> (applied in async functions) as a callback-free way to wait for and use a result, without blocking the event loop. (Futures and callbacks are still a viable alternative.)</p>
  <p>It also provides the <code>asyncio.Task()</code> class, a specialized subclass of <code>Future</code>  designed to wrap coroutines. Preferably invoked by using the <code>asyncio.ensure_future()</code> method. The intended use of asyncio tasks is to allow independently running tasks to run 'concurrently' with other tasks within the same event loop. My understanding is that <code>Tasks</code> are connected to the event loop which then automatically keeps driving the coroutine between <code>await</code> statements.</p>
  <p>I like the idea of being able to use concurrent Tasks without needing to use one of the <a href="https://docs.python.org/dev/library/concurrent.futures.html" rel="nofollow noreferrer"><code>Executor</code></a> classes, but I haven't found much elaboration on implementation.</p>
  <p>This is how I'm currently doing it:</p>
  
  <pre><code>import asyncio
  
  print('running async test')
  
  async def say_boo():
      i = 0
      while True:
          await asyncio.sleep(0)
          print('...boo {0}'.format(i))
          i += 1
  
  async def say_baa():
      i = 0
      while True:
          await asyncio.sleep(0)
          print('...baa {0}'.format(i))
          i += 1
  
  # wrap in Task object
  # -&gt; automatically attaches to event loop and executes
  boo = asyncio.ensure_future(say_boo())
  baa = asyncio.ensure_future(say_baa())
  
  loop = asyncio.get_event_loop()
  loop.run_forever()
  </code></pre>
  <p>In the case of trying to concurrently run two looping Tasks, I've noticed that unless the Task has an internal <code>await</code> expression, it will get stuck in the <code>while</code> loop, effectively blocking other tasks from running (much like a normal <code>while</code> loop). However, as soon the Tasks have to (a)wait, they seem to run concurrently without an issue.</p>
  <p>Thus, the <code>await</code> statements seem to provide the event loop with a foothold for switching back and forth between the tasks, giving the effect of concurrency.</p>
  <p>Example output with internal <code>await</code>:</p>
  <pre><code>running async test
  ...boo 0
  ...baa 0
  ...boo 1
  ...baa 1
  ...boo 2
  ...baa 2
  </code></pre>
  <p>Example output <em>without</em> internal <code>await</code>:</p>
  <pre><code>...boo 0
  ...boo 1
  ...boo 2
  ...boo 3
  ...boo 4
  </code></pre>
  <h2>Questions</h2>
  <p>Does this implementation pass for a 'proper' example of concurrent looping Tasks in <code>asyncio</code>?</p>
  <p>Is it correct that the only way this works is for a <code>Task</code> to provide a blocking point (<code>await</code> expression) in order for the event loop to juggle multiple tasks?</p>
  <h2>Edit</h2>
  <p>2022 UPDATE: Please note that the <code>asyncio</code> API has changed fairly substantially since this question was asked. See the newly marked as correct answer which now shows the correct use of the API given Python 3.10. I still recommend the answer from @dano for broader knowledge of how this works under the hood.</p>