asyncio.Queue conecta produtores e consumidores dentro de um event loop. Com maxsize, um produtor rápido espera quando o backlog atinge o limite, evitando crescimento de memória sem controle.

import asyncio

async def consumidor(fila: asyncio.Queue[int | None]) -> None:
    while (item := await fila.get()) is not None:
        try:
            await asyncio.sleep(0.05)
            print(item)
        finally:
            fila.task_done()
    fila.task_done()

async def main() -> None:
    fila: asyncio.Queue[int | None] = asyncio.Queue(maxsize=10)
    worker = asyncio.create_task(consumidor(fila))
    for item in range(5):
        await fila.put(item)
    await fila.put(None)
    await fila.join()
    await worker

asyncio.run(main())

Cada item retirado com get() precisa de um task_done(). O sentinela também conta como item e deve ser marcado. join() não encerra consumidores por conta própria; ele apenas aguarda o contador de trabalho chegar a zero.

Boas práticas

Use await em put() e get() para respeitar backpressure. A fila não recebe timeout diretamente; envolva a operação com a ferramenta de timeout apropriada da sua versão. Em aplicações reais, escolha uma política para falha do consumidor, cancelamento e itens que precisam ser tentados novamente.

Revise asyncio.TaskGroup para supervisionar vários consumidores. Se os produtores estiverem em threads, use queue.Queue em vez desta classe.

A documentação oficial de asyncio.Queue, consultada em 22 de julho de 2026, detalha a API e seus limites.