gc no Python: controle o coletor

Publicado em: 16/08/2026
Tempo de leitura: 7 minutos
Módulo de memória RAM representando gerenciamento de objetos com gc no Python

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, b

Depois 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.garbage após debugging.
  • Não manipule referenciadores fora de diagnóstico.
  • Prefira gerenciamento explícito de recursos.
  • Use tracemalloc para 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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Linhas de código representando rastreamento de execução com trace no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    trace no Python: rastreie execução

    Aprenda trace no Python para contar linhas, rastrear execução, listar funções, acumular cobertura e filtrar módulos.

    Ler mais

    Tempo de leitura: 6 minutos
    16/08/2026
    Notebook com gráficos de desempenho representando análise de perfis com pstats no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pstats no Python: analise perfis

    Aprenda pstats no Python para ordenar, filtrar, combinar e interpretar perfis do cProfile, callers, callees e tempos cumulativos.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Notebook com código representando exemplos executáveis testados com doctest no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    doctest no Python: teste exemplos

    Aprenda doctest no Python para executar exemplos em docstrings e arquivos, normalizar saídas e integrar documentação ao CI.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Código em tela representando navegação de classes e funções com pyclbr no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pyclbr no Python: inspecione módulos

    Aprenda pyclbr no Python para listar classes, funções, métodos e definições aninhadas sem importar nem executar o módulo.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Monitor com código binário representando instruções opcode do bytecode do Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    opcode no Python: explore o bytecode

    Aprenda opcode no Python para mapear instruções de bytecode, argumentos, saltos, caches e efeitos de pilha usando dis.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026
    Desenvolvedor analisando consumo de memória com tracemalloc no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tracemalloc no Python: encontre vazamentos

    Aprenda tracemalloc no Python para comparar snapshots, encontrar crescimento de memória e diagnosticar vazamentos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    15/08/2026