title: Get all items in an asyncio.Queue and return them
body: <p>How do you gather all items from an <a href="https://docs.python.org/3/library/asyncio-queue.html" rel="nofollow noreferrer"><code>asyncio.Queue</code></a> instance and return them as a result?</p>
  <p><strong>Caveats:</strong></p>
  <ul>
  <li>The total number of items put into the queue cannot be known ahead of time (but is finite, and will fit into memory).</li>
  <li>Multiple producers can add items to the queue; the producers themselves don't necessarily know when all items have been added to the queue.</li>
  </ul>
  <p><a href="https://asyncio.readthedocs.io/en/latest/producer_consumer.html" rel="nofollow noreferrer">The examples I have seen for consumers of an <code>asyncio.Queue</code></a> have not had to gather and return the results; they use the item from the queue but have no return value. They rely on side-effects to do their work, and don't care about returning a result.</p>
  <p>To be concrete, below is a simplistic example. The only way I figured out how to make this work is to provide an <a href="https://en.wikipedia.org/wiki/Parameter_(computer_programming)#Output_parameters" rel="nofollow noreferrer">output parameter</a>/<a href="https://softwareengineering.stackexchange.com/questions/322490/what-is-an-output-argument-as-refered-to-in-martins-clean-code">output argument</a> called <code>items</code> to the coroutine gathering the results from the queue:</p>
  <pre class="lang-py prettyprint-override"><code>import asyncio
  import random
  
  
  async def add_queue_item(item, queue):
      # simulate some work
      sleep_interval = random.randint(0, 3)
      await asyncio.sleep(sleep_interval)
      output_item = item + 1
      await queue.put(output_item)
  
  
  async def get_all_queue_items(queue, items):
      while True:
          items.append(await queue.get())
          queue.task_done()
  
  
  async def main():
      queue = asyncio.Queue()
      items = []
      producer_tasks = [asyncio.create_task(add_queue_item(item, queue)) for item in range(5)]
      collect_queue_items_task = asyncio.create_task(get_all_queue_items(queue, items))
      await queue.join()
      await asyncio.gather(*producer_tasks)
      collect_queue_items_task.cancel()
      print(items)
      assert sorted(items) == [1, 2, 3, 4, 5]
  
  
  asyncio.run(main())
  </code></pre>
  <p>Is there a way to implement <code>get_all_queue_items</code> above such that we can <code>await &lt;something&gt;</code> to get all the items — making it clear what's intended? i.e.,</p>
  <pre class="lang-py prettyprint-override"><code>    …
      await queue.join()
      await asyncio.gather(*producer_tasks)
      items = await &lt;something&gt;
      print(items)
      assert sorted(items) == [1, 2, 3, 4, 5]
  </code></pre>