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

    Monitor com código binário representando geração de arquivos pyc com py_compile no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    py_compile no Python: gere arquivos pyc

    Aprenda py_compile no Python para gerar arquivos pyc, validar sintaxe e controlar otimização e invalidação por timestamp ou hash.

    Ler mais

    Tempo de leitura: 7 minutos
    04/08/2026
    Editor de código representando correção de tabs e espaços com tabnanny no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tabnanny no Python: corrija indentação

    Aprenda tabnanny no Python para detectar tabs e espaços ambíguos, verificar projetos e evitar TabError e IndentationError.

    Ler mais

    Tempo de leitura: 7 minutos
    04/08/2026
    Código-fonte e sintaxe representando análise lexical com tokenize no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tokenize no Python: analise código-fonte

    Aprenda tokenize no Python para analisar tokens, comentários, encoding, posições e reconstruir código-fonte com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    04/08/2026
    Terminal de programação representando compilação de entradas interativas com codeop no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    codeop no Python: compile entradas interativas

    Aprenda codeop no Python para detectar entradas completas, compilar comandos de REPL e preservar __future__ com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    04/08/2026
    Desenvolvedor analisando estrutura de código e tabelas de símbolos com symtable no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    symtable no Python: escopos e símbolos

    Aprenda symtable no Python para analisar escopos, símbolos, globals, nonlocals, closures, imports, annotations e type parameters.

    Ler mais

    Tempo de leitura: 7 minutos
    03/08/2026
    Monitor com código binário representando análise de bytecode com dis no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    dis no Python: entenda o bytecode

    Aprenda dis no Python para desmontar bytecode, analisar instruções, caches adaptativos, posições, tracebacks e detalhes do CPython.

    Ler mais

    Tempo de leitura: 7 minutos
    03/08/2026