compileall no Python: compile diretórios

Publicado em: 04/08/2026
Tempo de leitura: 7 minutos
Desenvolvedor trabalhando em automação de build e compilação de diretórios com compileall no Python

Projetos e pacotes Python podem conter centenas de arquivos-fonte. Compilá-los individualmente com py_compile funciona, mas exige percorrer diretórios, aplicar filtros e gerenciar falhas. O módulo compileall no Python automatiza a geração de arquivos .pyc em árvores inteiras, com recursão, paralelismo, níveis de otimização, exclusões e caminhos adequados para tracebacks.

Neste guia, você aprenderá a usar a interface de linha de comando e as funções compile_dir(), compile_file() e compile_path(). O conteúdo complementa nossos artigos sobre py_compile, bytecode com dis, tokenize, tabnanny e tracebacks.

Quando usar compileall

Compileall é útil em instalação de bibliotecas, criação de imagens de container, validação de sintaxe em builds e ambientes onde os usuários podem ler o pacote, mas não possuem permissão para criar __pycache__.

Ele não transforma o projeto em um executável nem substitui testes. A compilação comprova que cada arquivo analisado possui sintaxe compatível com o interpretador atual.

Compilar um diretório pela terminal

python -m compileall src

O comando percorre src recursivamente, compila arquivos .py e grava caches nos caminhos PEP 3147, normalmente dentro de __pycache__.

Compilar vários caminhos

python -m compileall src tests ferramentas/script.py

Argumentos posicionais podem ser arquivos ou diretórios. Em diretórios, a busca é recursiva por padrão.

Execução sem argumentos

Sem argumentos, a interface se comporta como se recebesse -l e os diretórios de sys.path.

python -m compileall

Esse comportamento pode percorrer muito mais código que o esperado. Em automação, informe explicitamente as raízes do projeto.

Não recursivo com -l

A opção -l compila apenas arquivos diretamente no diretório informado.

python -m compileall -l src

Subdiretórios não são visitados. A opção é útil para diretórios planos ou para uma primeira etapa controlada.

Controlar profundidade

-r define o máximo de níveis recursivos.

python -m compileall -r 2 src

-r 0 equivale ao comportamento não recursivo. Quando -r é informado, -l deixa de ser considerado.

Forçar recompilação

Normalmente caches atualizados são ignorados. -f força a reconstrução.

python -m compileall -f src

Use em builds limpos, mudanças de política de invalidação ou diagnóstico. Forçar sempre aumenta tempo e gravações sem benefício quando os artefatos já estão corretos.

Saída quiet

-q omite a lista de arquivos compilados, mas mantém erros. -qq suprime toda a saída.

python -m compileall -q src

Mesmo sem mensagens, o pipeline deve verificar o código de saída.

Paralelismo com -j

-j N usa workers para compilar arquivos em paralelo.

python -m compileall -j 4 src

Com -j 0, o número é escolhido a partir de os.process_cpu_count(). O paralelismo ajuda em árvores grandes, mas pode saturar CPU e armazenamento em containers pequenos.

Múltiplos níveis de otimização

A opção -o pode ser repetida.

python -m compileall -o 0 -o 1 -o 2 src

Cada nível gera uma variante de cache. O nível 1 remove asserts; o nível 2 também remove muitas docstrings. Não use otimização sem entender essas alterações.

Quando variantes de otimização possuem conteúdo idêntico, --hardlink-dupes pode usar hardlinks.

python -m compileall \
  -o 0 -o 1 -o 2 \
  --hardlink-dupes \
  src

O filesystem precisa oferecer hardlinks e os arquivos devem permanecer no mesmo volume. Ferramentas de empacotamento e cópia podem desfazer ou preservar a relação de maneiras diferentes.

Modo de invalidação

--invalidation-mode aceita timestamp, checked-hash ou unchecked-hash.

python -m compileall \
  --invalidation-mode checked-hash \
  src

Timestamp compara metadados. Hash verificado compara o conteúdo ao importar. Hash não verificado confia em um sistema externo para manter os caches atualizados.

SOURCE_DATE_EPOCH

Sem a variável, o padrão é timestamp. Com SOURCE_DATE_EPOCH, o padrão passa a hash verificado, ajudando builds reproduzíveis.

Em pipelines determinísticos, informe também a política explicitamente para tornar a intenção visível.

Filtrar caminhos com -x

-x recebe uma expressão regular aplicada ao caminho completo.

python -m compileall \
  -x '[/\\](tests|migrations|vendor)[/\\]' \
  src

Se a regex encontrar correspondência, o arquivo é ignorado. Teste o padrão em Windows e Unix, pois separadores diferem.

Ler uma lista com -i

-i adiciona arquivos e diretórios lidos de um arquivo.

python -m compileall -i caminhos.txt

Use -i - para ler de stdin. Essa opção facilita integração com ferramentas que já selecionaram os arquivos.

Caminhos em tracebacks com -d

-d prefixa o caminho registrado dentro do bytecode.

python -m compileall \
  -d /app \
  src

O caminho de build pode ser diferente do caminho de implantação. Um valor coerente torna tracebacks posteriores mais úteis.

Remover e adicionar prefixos

-s remove um prefixo dos caminhos e -p adiciona outro.

python -m compileall \
  -s /workspace/projeto \
  -p /app \
  /workspace/projeto/src

-s e -p podem ser usados juntos, mas não com -d. Isso é útil em builds reproduzíveis e containers.

-e DIR ignora symlinks que apontam para fora do diretório permitido.

python -m compileall -e src src

Essa proteção reduz a chance de sair da raiz por um link. Ainda assim, escolha uma raiz controlada e execute com permissões mínimas.

Formato legacy com -b

-b grava .pyc ao lado do arquivo-fonte, no formato legado.

python -m compileall -b src

Esse modo pode sobrescrever caches criados por outra versão e elimina a convivência fornecida por __pycache__. Use apenas por compatibilidade específica.

compile_dir()

A função programática principal percorre uma árvore e retorna True se todos os arquivos forem compilados.

import compileall

ok = compileall.compile_dir(
    "src",
    quiet=1,
)

if not ok:
    raise SystemExit("Falha ao compilar")

A documentação oficial de compileall descreve opções equivalentes à CLI.

Filtros com expressão regular

rx recebe um objeto compilado e usa seu método search().

import re

ok = compileall.compile_dir(
    "src",
    rx=re.compile(r"[/\\](tests|vendor)[/\\]"),
    quiet=1,
)

Um arquivo ignorado não é falha. Registre exclusões importantes para evitar omitir código de produção por engano.

Paralelismo programático

ok = compileall.compile_dir(
    "src",
    workers=0,
    quiet=1,
)

workers=0 usa a quantidade de CPUs. Valores negativos geram ValueError. Se a plataforma não suportar múltiplos workers, a função pode continuar sequencialmente.

Vários níveis em uma chamada

ok = compileall.compile_dir(
    "src",
    optimize=[0, 1, 2],
    hardlink_dupes=True,
    quiet=1,
)

A sequência produz várias variantes por fonte. Hardlinks só consolidam arquivos de conteúdo igual.

compile_file()

compile_file() compila um único arquivo com a mesma política de caminhos, otimização e invalidação.

ok = compileall.compile_file(
    "src/app.py",
    force=True,
    quiet=1,
)

Ela devolve verdadeiro em sucesso e também quando um filtro rx decide ignorar o arquivo.

compile_path()

compile_path() percorre entradas de sys.path.

ok = compileall.compile_path(
    skip_curdir=True,
    quiet=1,
)

Diferentemente de compile_dir(), o limite de profundidade padrão é zero. Em aplicações, compilar todo o sys.path raramente é necessário.

sys.pycache_prefix

A compilação respeita sys.pycache_prefix. O cache gerado será útil somente se o runtime utilizar o mesmo prefixo.

Containers podem direcionar caches para um diretório gravável separado. Documente a configuração entre build e execução.

Indisponibilidade em WASI

A documentação marca compileall como indisponível em WASI. Ferramentas destinadas a WebAssembly precisam detectar a plataforma e não presumir que a API existe ou funciona.

Pipeline de container

RUN python -m compileall \
    -q \
    -j 0 \
    --invalidation-mode checked-hash \
    /app

Execute após copiar dependências e código. Avalie se os caches aumentam a imagem mais do que reduzem o tempo de inicialização.

Compilação não executa testes

Um arquivo pode compilar e ainda conter imports ausentes, erros de lógica, incompatibilidades de plataforma e falhas de tipo.

Use compileall como etapa rápida, seguida de testes, lint, type checking e inicialização real do pacote.

Segurança

Compilar não executa o corpo dos módulos, o que é mais seguro que importá-los. Porém, árvores não confiáveis podem ser enormes, conter symlinks e consumir CPU ou armazenamento.

Limite raiz, profundidade, quantidade de arquivos, workers e espaço disponível. Não importe os caches produzidos por código não confiável.

Erros frequentes

  • Executar sem argumentos e compilar todo o sys.path.
  • Usar -b sem necessidade.
  • Aplicar regex que exclui arquivos importantes.
  • Usar workers ilimitados em container pequeno.
  • Gerar vários níveis sem considerar espaço.
  • Configurar caminhos de traceback incorretos.
  • Usar unchecked-hash sem build confiável.
  • Confundir compilação com testes.

Boas práticas

  • Informe raízes explicitamente.
  • Use caches PEP 3147.
  • Escolha invalidação conforme o build.
  • Controle workers e profundidade.
  • Teste filtros e symlinks.
  • Use caminhos de traceback iguais ao ambiente final.
  • Verifique o valor retornado ou código de saída.
  • Execute testes após a compilação.

Conclusão

O módulo compileall no Python transforma a compilação de árvores inteiras em uma etapa controlável de instalação e build. Ele oferece recursão, paralelismo, filtros, múltiplos níveis de otimização, invalidação por hash e ajuste dos caminhos gravados no bytecode.

Uma configuração eficiente depende do ambiente: raízes explícitas, workers moderados, caches versionados pelo interpretador e política de invalidação coerente. Assim, compileall prepara arquivos .pyc sem atravessar diretórios indevidos nem confundir validação sintática com qualidade funcional.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Programador analisando código para identificar tipos MIME de arquivos no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes.guess_file_type: detecte tipos MIME

    Aprenda mimetypes.guess_file_type no Python para detectar tipos MIME em caminhos, URLs, uploads e respostas HTTP com fallbacks seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    13/09/2026
    Componentes de servidor representando interpretadores Python executando em paralelo
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    InterpreterPoolExecutor: paralelismo real no Python

    Aprenda InterpreterPoolExecutor no Python para executar tarefas CPU-bound em interpretadores isolados com paralelismo real.

    Ler mais

    Tempo de leitura: 6 minutos
    13/09/2026
    Microprocessador representando CPUs disponíveis para um processo Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.process_cpu_count: conte CPUs disponíveis

    Aprenda os.process_cpu_count no Python para dimensionar workers conforme as CPUs realmente disponíveis ao processo.

    Ler mais

    Tempo de leitura: 4 minutos
    12/09/2026
    Laptop com código digital representando dados BLOB no SQLite
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sqlite3.Blob: leia BLOBs sem carregar tudo na memória

    Aprenda sqlite3.Blob no Python para ler e gravar BLOBs em partes, reduzir memória e trabalhar com dados binários no SQLite.

    Ler mais

    Tempo de leitura: 5 minutos
    12/09/2026
    Análise estatística para random.binomialvariate no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    random.binomialvariate: simule distribuições binomiais

    Aprenda random.binomialvariate no Python para simular sucessos, validar probabilidades e analisar cenários binomiais com clareza.

    Ler mais

    Tempo de leitura: 6 minutos
    11/09/2026
    Código Python analisado com inspect.signature.bind
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    inspect.signature.bind: valide argumentos de funções

    Aprenda inspect.signature.bind no Python para validar argumentos, aplicar padrões e criar decorators e APIs dinâmicas com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    11/09/2026