O módulo gc no Python expõe a interface do coletor de lixo cíclico do interpretador. O CPython já libera a maioria dos objetos por contagem de referências, mas ciclos como “objeto A aponta para B e B aponta para A” podem permanecer mesmo quando a aplicação perdeu todas as referências externas. O coletor complementar identifica esses grupos inalcançáveis e tenta liberá-los.
Na maior parte dos programas, você não precisa alterar nada. O coletor automático possui heurísticas adequadas para uso geral. A API se torna útil em diagnóstico de vazamentos, serviços de longa duração, processos que fazem fork(), testes de estruturas cíclicas e observabilidade de pausas de coleta.
Contagem de referências e ciclos
Quando a última referência a um objeto comum desaparece, o CPython geralmente o destrói imediatamente. Um ciclo impede que os contadores cheguem a zero.
class No:
def __init__(self, nome):
self.nome = nome
self.proximo = None
a = No("a")
b = No("b")
a.proximo = b
b.proximo = a
del a, bDepois do del, o programa não consegue mais alcançar os nós, mas eles ainda se referenciam. O coletor cíclico pode removê-los em uma varredura posterior.
Verifique se o coletor está ativo
import gc
print(gc.isenabled())
gc.enable() ativa a coleta automática e gc.disable() a desativa. Desativar não interrompe a contagem de referências; apenas suspende a busca por ciclos.
Não desative sem medir
Algumas aplicações que comprovadamente não criam ciclos podem desativar o coletor em uma seção crítica para reduzir pausas. Essa decisão exige testes e deve ser temporária.
import gc
estava_ativo = gc.isenabled()
try:
gc.disable()
executar_secao_controlada()
finally:
if estava_ativo:
gc.enable()
Se qualquer biblioteca criar ciclos durante esse intervalo, eles permanecerão até uma coleta posterior. Não use essa técnica como otimização automática.
Force uma coleta
gc.collect() executa uma coleta completa por padrão e retorna a soma dos objetos coletados e não coletáveis.
import gc
removidos = gc.collect()
print(f"Objetos processados: {removidos}")
Chamadas frequentes podem piorar o desempenho. Use coleta manual em testes, diagnósticos e pontos arquiteturais bem definidos, não dentro de cada requisição.
Escolha a geração
O coletor separa objetos por gerações conforme sobrevivem a varreduras. Objetos novos entram na geração mais jovem; sobreviventes avançam para gerações mais antigas.
gc.collect(0)
gc.collect(1)
gc.collect(2)
A semântica intermediária mudou durante a série Python 3.14. Código que dependa de detalhes das gerações deve ser testado na versão exata usada em produção. Uma coleta da geração mais antiga também limpa várias free lists internas, embora alguns itens, como floats, possam permanecer.
Consulte estatísticas
gc.get_stats() retorna um dicionário por geração com quantidade de coletas, objetos coletados e objetos não coletáveis.
for geracao, dados in enumerate(gc.get_stats()):
print(geracao, dados)
Observe tendências ao longo do tempo. Uma única leitura não prova vazamento. Compare o comportamento sob cargas equivalentes e relacione com memória do processo.
Veja contadores e limites
print(gc.get_count())
print(gc.get_threshold())
get_count() mostra contadores atuais de alocações e coletas. get_threshold() informa os limites usados pela heurística automática.
Ajuste thresholds com cautela
gc.set_threshold() muda a frequência das coletas. Definir o primeiro limite como zero desativa a coleta automática.
antigos = gc.get_threshold()
try:
gc.set_threshold(1000, 15, 15)
executar_carga()
finally:
gc.set_threshold(*antigos)
Um limite menor coleta com mais frequência e pode reduzir crescimento temporário, mas aumenta overhead. Um limite maior reduz pausas e pode elevar memória. A implementação free-threaded também considera crescimento de memória e volume líquido de alocações.
Use callbacks para observabilidade
gc.callbacks contém funções chamadas antes e depois de cada coleta.
import gc
import time
inicio = {}
def observar(fase, info):
geracao = info["generation"]
if fase == "start":
inicio[geracao] = time.perf_counter()
else:
duracao = time.perf_counter() - inicio.pop(geracao, 0)
print(
geracao,
info["collected"],
info["uncollectable"],
duracao,
)
gc.callbacks.append(observar)
Callbacks executam durante uma operação sensível. Mantenha-os rápidos, sem alocações excessivas, bloqueios ou chamadas de rede. Remova o callback quando terminar.
Diagnostique com flags de debug
gc.set_debug() habilita mensagens em stderr.
gc.set_debug(gc.DEBUG_STATS)
DEBUG_COLLECTABLE e DEBUG_UNCOLLECTABLE mostram objetos encontrados. A saída pode ser enorme e conter dados sensíveis; use apenas em ambiente controlado.
DEBUG_LEAK e DEBUG_SAVEALL
DEBUG_LEAK combina flags e inclui DEBUG_SAVEALL. Nesse modo, objetos inalcançáveis são preservados em gc.garbage em vez de liberados.
gc.set_debug(gc.DEBUG_LEAK)
gc.collect()
print(len(gc.garbage))
Preservar tudo aumenta a memória intencionalmente. Depois da inspeção, restaure as flags, limpe gc.garbage e execute outra coleta.
gc.set_debug(0)
gc.garbage.clear()
gc.collect()
Entenda gc.garbage
Desde a PEP 442, objetos Python com __del__() normalmente podem ser coletados mesmo em ciclos. Portanto, gc.garbage costuma ficar vazio, exceto por extensões C específicas ou quando DEBUG_SAVEALL está ativo.
Uma lista não vazia não deve ser ignorada. Registre tipos e origens sem serializar objetos arbitrários ou chamar métodos potencialmente perigosos.
Descubra objetos rastreados
gc.is_tracked() informa se um objeto participa do coletor cíclico.
print(gc.is_tracked(10))
print(gc.is_tracked([]))
print(gc.is_tracked({"chave": 1}))
Tipos atômicos normalmente não são rastreados. Algumas estruturas simples podem deixar de ser rastreadas por otimização e voltar a ser rastreadas quando recebem valores complexos.
Liste objetos com cuidado
gc.get_objects() devolve objetos rastreados, opcionalmente de uma geração.
objetos = gc.get_objects()
print(len(objetos))
A lista pode ser enorme, aumenta temporariamente a memória e contém objetos internos da aplicação. Use em processo de diagnóstico, filtre por tipo e não exponha o conteúdo por endpoints administrativos sem proteção.
Encontre referenciadores
gc.get_referrers(objeto) mostra containers rastreados que apontam diretamente para o alvo.
gc.collect()
referenciadores = gc.get_referrers(alvo)
for item in referenciadores:
print(type(item))
O resultado pode incluir frames de depuração, o próprio código que está inspecionando e objetos em estado temporário. A documentação recomenda usar a função apenas para debugging. Evite chamar métodos dos objetos retornados.
Encontre objetos referenciados
gc.get_referents() percorre referências visitadas pelo protocolo C tp_traverse.
for item in gc.get_referents(alvo):
print(type(item))
A lista não representa necessariamente todas as referências semanticamente acessíveis. Ela contém apenas objetos que o tipo precisa apresentar ao coletor para detectar ciclos.
Finalização e ressurreição
gc.is_finalized() informa se a finalização já ocorreu. Um método __del__() pode, de forma problemática, ressuscitar o objeto ao armazená-lo novamente.
ressuscitado = None
class Lazarus:
def __del__(self):
global ressuscitado
ressuscitado = self
obj = Lazarus()
del obj
gc.collect()
print(gc.is_finalized(ressuscitado))
Evite lógica complexa em __del__(). Prefira context managers, close() explícito e weakref.finalize(). Veja weakref no Python.
Freeze antes de fork
gc.freeze() move objetos rastreados para uma geração permanente ignorada por coletas futuras. Em servidores que fazem fork() sem exec(), isso pode melhorar compartilhamento copy-on-write.
gc.disable()
carregar_aplicacao()
gc.freeze()
pid = os.fork()
if pid == 0:
gc.enable()
O padrão exige planejamento: desative cedo no processo pai, congele imediatamente antes do fork e reative nos filhos. Não aplique em plataformas ou arquiteturas que não usam esse modelo.
Descongele quando necessário
gc.unfreeze() devolve os objetos permanentes à geração antiga. gc.get_freeze_count() informa quantos estão congelados.
print(gc.get_freeze_count())
gc.unfreeze()
Descongelar pode provocar uma coleta grande mais tarde. Meça memória e latência.
GC e vazamentos de memória
Nem todo crescimento é ciclo não coletado. Caches, filas, logs, pools, módulos e variáveis globais podem manter referências válidas. O GC não libera objetos que continuam alcançáveis.
Use tracemalloc no Python para comparar alocações e snapshots. Combine com gc.get_referrers() apenas depois de localizar tipos suspeitos.
Contagem de objetos por tipo
from collections import Counter
import gc
contagem = Counter(type(obj).__name__ for obj in gc.get_objects())
for nome, total in contagem.most_common(20):
print(nome, total)
Faça snapshots em momentos equivalentes. A própria análise cria objetos e pode distorcer números pequenos.
Evite ciclos desnecessários
Callbacks, closures, observers e estruturas pai-filho criam ciclos facilmente. Use referências fracas quando a relação não representa propriedade. Remova listeners e tasks quando o componente é encerrado.
O artigo sobre vazamentos de memória no Python mostra um processo de diagnóstico mais amplo.
Não chame collect em toda requisição
Forçar uma coleta completa depois de cada operação geralmente reduz throughput e aumenta latência. Se a memória só cai após collect(), investigue por que ciclos estão sendo criados em grande volume ou por que a heurística não acompanha a carga.
Segurança e auditoria
Funções como get_objects(), get_referrers() e get_referents() emitem eventos de auditoria e podem revelar dados internos. Restrinja essas ferramentas a administradores, logs protegidos e ambientes de diagnóstico.
Boas práticas
- Deixe o coletor automático ativo por padrão.
- Meça antes de alterar thresholds.
- Use callbacks leves para métricas.
- Limpe flags e
gc.garbageapós debugging. - Não manipule referenciadores fora de diagnóstico.
- Prefira gerenciamento explícito de recursos.
- Use
tracemallocpara localizar alocações. - Teste na versão exata do Python.
Conclusão
O gc no Python permite observar e controlar a coleta de ciclos que complementa a contagem de referências do CPython. Estatísticas, callbacks, flags, inspeção de referências e congelamento ajudam em cenários avançados.
Use a API com cuidado: introspecção cria overhead e pode expor objetos internos. Consulte a documentação oficial do gc e o guia de design do garbage collector do CPython.







