✅ Artigo atualizado em Setembro 2026 Reescrevemos o exemplo produtor-consumidor para que as threads rodem de fato ao mesmo tempo e terminem corretamente (com sentinela), explicamos a ordem da
PriorityQueuee conferimos os exemplos no Python 3.13.
Salve salve Pythonista!
Hoje vamos mergulhar em um tópico extremamente relevante e útil no universo Python: as filas.
Quem já trabalhou com processamento de tarefas em série sabe o quanto é importante entender o gerenciamento de filas.
Estaremos utilizando a biblioteca queue, uma grande aliada quando temos tarefas que precisam ser processadas de forma ordenada.
Obter um controle mais aprimorado nas operações de fila em Python permite aprimorar o desempenho do seu código, especialmente em aplicações que fazem muito uso de filas para tarefas como gerenciamento de threads, gerenciamento de operações em tempo real, entre outros.
Vá Direto ao Assunto…
- Introdução a Filas
- Filas em Python
- Gerenciamento de Filas
- FIFO, LIFO, Priority Queue
- Caso Prático: Producer-Consumer com Threading
Introdução a Filas
As filas são estruturas de dados essenciais que obedecem ao princípio de operação FIFO (First-In-First-Out), ou em português, “Primeiro a entrar, primeiro a sair”.
Basicamente, a ideia é que o primeiro elemento que é adicionado à fila será o primeiro a ser removido dela.
É como uma fila de supermercado, cada cliente que chega vai para o fim da fila e o cliente no início da fila é o próximo a ser atendido.
1
2
3
4
5
6
7
fila = ['Cliente 1', 'Cliente 2', 'Cliente 3']
fila.append('Cliente 4')
# A fila agora é ['Cliente 1', 'Cliente 2', 'Cliente 3', 'Cliente 4']
atendido = fila.pop(0)
# atendido agora é 'Cliente 1'
Antes de seguir… Está curtindo esse conteúdo? ![]()
Que tal receber 30 dias de conteúdo GRATUITAMENTE direto na sua Caixa de Entrada?
Filas em Python
Nativa no Python, basta importá-la com a declaração import queue. O módulo queue do Python oferece três tipos principais de classes: Queue, LifoQueue e PriorityQueue (há também a SimpleQueue, uma fila FIFO mais enxuta, sem controle de tarefas, disponível desde o Python 3.7). Todas são seguras para uso entre threads (thread-safe):
- Queue: É o primeiro tipo de fila. Ele segue a propriedade FIFO onde o primeiro elemento inserido é o primeiro a ser extraído.
- LifoQueue: Esta é a fila que segue a propriedade LIFO (Last-In-First-Out) onde o último elemento inserido é o primeiro a ser extraído.
-
PriorityQueue: Não segue nenhuma das propriedades acima, FIFO ou LIFO. Esta fila segue o conceito de “ordem de prioridade”: os elementos ficam ordenados e o de menor valor é extraído primeiro. Por isso é comum usar tuplas no formato
(prioridade, dado), em que o número1sai antes do2.
Por exemplo, essa seria a sintaxe básica para cada tipo de fila:
1
2
3
4
5
import queue
fila_fifo = queue.Queue()
fila_lifo = queue.LifoQueue()
fila_prioridade = queue.PriorityQueue()
Gerenciamento de Filas
Com a biblioteca queue, pode-se adicionar elementos na fila utilizando o método put e remover utilizando o método get.
1
2
3
4
5
6
7
import queue
fila = queue.Queue()
fila.put("Primeiro da fila")
fila.put("Segundo da fila")
print(fila.get())
E a saída será:
1
Primeiro da fila
Falando em filas: O Ebookr.ai usa filas de processamento para gerar ebooks de forma escalável. É uma plataforma que criei para criar ebooks profissionais com IA sobre qualquer tema - com infográficos automáticos e exportação em PDF. Conhece lá!
FIFO, LIFO, Priority Queue
Como já discutimos, quando utilizamos filas, temos três abordagens principais: FIFO, LIFO e Priority Queue. Veja a diferença entre elas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import queue
# Exemplo de FIFO
fila_FIFO = queue.Queue()
fila_FIFO.put("Primeiro da fila")
fila_FIFO.put("Segundo da fila")
print(fila_FIFO.get())
# Saída será: Primeiro da fila
# Exemplo de LIFO
fila_LIFO = queue.LifoQueue()
fila_LIFO.put("Primeiro da fila")
fila_LIFO.put("Segundo da fila")
print(fila_LIFO.get())
# Saída será: Segundo da fila
# Exemplo de PriorityQueue
fila_prioridade = queue.PriorityQueue()
fila_prioridade.put((2, "Primeiro da fila"))
fila_prioridade.put((1, "Segundo da fila"))
print(fila_prioridade.get())
# Saída será: (1, 'Segundo da fila')
Coordenar produtores e consumidores exige entender bem estruturas de dados e funções - e é exatamente essa base que a Jornada Python constrói, com projetos guiados do zero ao avançado:
Caso Prático: Producer-Consumer com Threading
Um uso clássico da queue é o padrão produtor-consumidor: algumas threads produzem itens e os colocam na fila, enquanto outras threads, ao mesmo tempo, retiram e processam esses itens.
No exemplo abaixo, dois produtores e três consumidores rodam ao mesmo tempo (de forma concorrente). A fila tem maxsize=3: quando ela enche, o put() bloqueia o produtor até algum consumidor liberar espaço, e quando ela esvazia, o get() bloqueia o consumidor até chegar um novo item.
Para encerrar os consumidores, usamos uma sentinela (None): depois que os produtores terminam, colocamos na fila uma sentinela por consumidor, e cada consumidor sai do loop ao recebê-la.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import queue
import threading
import time
import random
FIM = None # sentinela: avisa o consumidor que não há mais trabalho
def produtor(fila, id_produtor):
"""Produz itens e coloca na fila"""
for i in range(5):
item = f"Item-{id_produtor}-{i}"
fila.put(item) # bloqueia se a fila estiver cheia
print(f"Produtor {id_produtor} produziu: {item}")
time.sleep(random.uniform(0.1, 0.5))
def consumidor(fila, id_consumidor):
"""Consome itens da fila até receber a sentinela"""
while True:
item = fila.get() # bloqueia até ter um item
try:
if item is FIM:
break
print(f"Consumidor {id_consumidor} processou: {item}")
time.sleep(random.uniform(0.2, 0.6))
finally:
fila.task_done()
# Fila compartilhada e pequena, para mostrar o bloqueio do put()
fila_trabalho = queue.Queue(maxsize=3)
produtores = [
threading.Thread(target=produtor, args=(fila_trabalho, i))
for i in range(2)
]
consumidores = [
threading.Thread(target=consumidor, args=(fila_trabalho, i))
for i in range(3)
]
# Consumidores e produtores rodam ao mesmo tempo
for c in consumidores:
c.start()
for p in produtores:
p.start()
# Espera os produtores terminarem de produzir
for p in produtores:
p.join()
# Uma sentinela por consumidor, para cada um encerrar o loop
for _ in consumidores:
fila_trabalho.put(FIM)
# Espera todos os itens (e sentinelas) serem processados
fila_trabalho.join()
for c in consumidores:
c.join()
print("Todos os itens foram processados!")
Uma saída possível é:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Produtor 0 produziu: Item-0-0
Consumidor 0 processou: Item-0-0
Produtor 1 produziu: Item-1-0
Consumidor 1 processou: Item-1-0
Produtor 1 produziu: Item-1-1
Consumidor 2 processou: Item-1-1
Produtor 0 produziu: Item-0-1
Consumidor 1 processou: Item-0-1
Produtor 1 produziu: Item-1-2
Consumidor 0 processou: Item-1-2
Produtor 0 produziu: Item-0-2
Consumidor 2 processou: Item-0-2
Produtor 1 produziu: Item-1-3
Consumidor 0 processou: Item-1-3
Produtor 1 produziu: Item-1-4
Consumidor 1 processou: Item-1-4
Produtor 0 produziu: Item-0-3
Consumidor 2 processou: Item-0-3
Produtor 0 produziu: Item-0-4
Consumidor 0 processou: Item-0-4
Todos os itens foram processados!
Como as threads rodam ao mesmo tempo e os tempos de espera são aleatórios, a ordem das linhas muda a cada execução (às vezes o consumidor imprime antes do produtor, por exemplo).
Alguns detalhes importantes:
- Os consumidores são iniciados antes dos produtores terminarem, então há concorrência de verdade. Mesmo com uma fila pequena (
maxsize=3) e muitos itens, o programa não trava, porque sempre há alguém consumindo. - Cada
get()é seguido de umtask_done()(inclusive o da sentinela, graças aofinally). É isso que permite aofila_trabalho.join()saber que todo o trabalho foi concluído. - Não usamos
get(timeout=...)para decidir quando parar: um consumidor lento ou um produtor demorado poderia fazer a fila ficar vazia por alguns segundos sem que o trabalho tivesse acabado.
A partir do Python 3.13, a classe Queue também ganhou o método shutdown(), outra forma de avisar as threads de que a fila foi encerrada. A sentinela, porém, funciona em qualquer versão.
Conclusão
Neste artigo, abordamos os conceitos de fila, como elas são implementadas em Python através do módulo queue e como gerenciá-las.
Também discutimos os princípios FIFO, LIFO e Priority Queue.
Se você precisa de uma fila simples, sem threads, o deque do pacote collections é uma boa alternativa. Já em código com asyncio, vale conhecer a programação assíncrona no Python.
Espero que esses conhecimentos te ajudem a arrasar no que diz respeito ao gerenciamento de filas.
Não esqueça de compartilhar com seus amigos programadores.
Quer firmar a base de Python e POO que esses recursos pressupõem, com projetos guiados do básico ao avançado? Conheça a Jornada Python, nosso curso de Python completo.
E que a força do Python esteja com você! ![]()
"Porque o Senhor dá a sabedoria, e da sua boca vem a inteligência e o entendimento" Pv 2:6