zipapp no Python: crie executáveis .pyz

Publicado em: 13/08/2026
Tempo de leitura: 7 minutos
Pastas organizadas representando aplicações empacotadas em arquivos .pyz com zipapp no Python

O módulo zipapp no Python cria arquivos ZIP executáveis contendo uma aplicação Python. Esses arquivos costumam usar a extensão .pyz e podem ser iniciados com python aplicativo.pyz. Em sistemas POSIX, também podem receber um shebang e permissão de execução para funcionar como um comando comum.

O formato é útil para distribuir utilitários internos, ferramentas de linha de comando, scripts administrativos e aplicações puramente Python em um único arquivo. Ele não transforma o programa em binário nativo e não inclui automaticamente o interpretador. A máquina de destino precisa ter uma versão compatível do Python e todas as dependências devem ser compatíveis com execução dentro de um ZIP.

Como funciona um arquivo .pyz

Um Python Zip Application é um ZIP padrão que contém __main__.py na raiz. Ao executar o arquivo, o interpretador adiciona o próprio ZIP a sys.path e roda esse módulo como ponto de entrada.

meu_app/
├── __main__.py
├── comandos.py
└── dados/
    └── config.json

Com essa estrutura, o comando abaixo gera meu_app.pyz:

python -m zipapp meu_app

Depois:

python meu_app.pyz

O processo usa o mecanismo normal de imports dentro do arquivo. Para compreender como recursos empacotados devem ser acessados, consulte o guia de importlib.resources no Python.

Criar um entry point automaticamente

Se o diretório não possui __main__.py, a opção -m cria um ponto de entrada que importa um callable sem argumentos.

python -m zipapp meu_app \
  -m "meu_app.cli:main" \
  -o ferramenta.pyz

A função precisa estar dentro do conteúdo empacotado:

# meu_app/cli.py
def main():
    print('Aplicação iniciada')

O formato exigido é pacote.modulo:funcao. Não use -m quando o diretório já contém __main__.py, pois as duas estratégias representam pontos de entrada concorrentes.

Adicionar um shebang

A opção -p adiciona uma linha de interpretador ao início do ZIP. Em POSIX, o arquivo também recebe o bit executável.

python -m zipapp meu_app \
  -p "/usr/bin/env python3" \
  -o ferramenta.pyz

./ferramenta.pyz

O shebang precisa ser portável para o público-alvo. /usr/bin/env python3 costuma ser mais flexível que um caminho fixo, mas ainda pressupõe que python3 esteja disponível e seja compatível com o código.

Comprimir ou não comprimir

Por padrão, os arquivos são armazenados sem compressão. A opção --compress usa deflate:

python -m zipapp meu_app --compress -o ferramenta.pyz

A compressão reduz o tamanho, mas pode aumentar o tempo de criação e de leitura. Meça o impacto com o conteúdo real. Arquivos de código geralmente comprimem bem, enquanto formatos já compactados, como imagens JPEG, quase não diminuem.

Usar a API create_archive()

O mesmo processo pode ser automatizado por código.

import zipapp

zipapp.create_archive(
    source='meu_app',
    target='dist/ferramenta.pyz',
    interpreter='/usr/bin/env python3',
    main='meu_app.cli:main',
    compressed=True,
)

source pode ser um diretório, um arquivo existente ou um stream binário. target pode ser um caminho ou stream aberto para escrita binária. Quando streams são fornecidos, o chamador é responsável por fechá-los.

Filtrar arquivos incluídos

O parâmetro filter recebe um Path relativo e decide se o item entra no pacote.

from pathlib import Path
import zipapp

IGNORADOS = {'__pycache__', '.git', '.pytest_cache'}

def incluir(caminho: Path) -> bool:
    if any(parte in IGNORADOS for parte in caminho.parts):
        return False
    return caminho.suffix not in {'.pyc', '.log', '.env'}

zipapp.create_archive(
    'meu_app',
    'dist/meu_app.pyz',
    filter=incluir,
    compressed=True,
)

Excluir .env, chaves, logs, testes confidenciais e artefatos locais é essencial. Gere o pacote a partir de uma árvore limpa e revise seu conteúdo antes de distribuir.

Incluir dependências Python

Dependências puramente Python podem ser instaladas no diretório da aplicação antes do empacotamento:

python -m pip install \
  --requirement requirements.txt \
  --target build/meu_app

python -m zipapp build/meu_app \
  -m "meu_app.cli:main" \
  -o dist/meu_app.pyz

Fixe versões e hashes quando o processo exige reprodutibilidade. Não execute pip install diretamente sobre a pasta de código-fonte; use um diretório de build descartável.

A limitação das extensões C

Módulos compilados como arquivos .so, .pyd ou outras bibliotecas nativas não podem ser carregados diretamente de dentro do ZIP, porque o loader do sistema operacional exige um arquivo real no sistema de arquivos.

Pacotes como NumPy, algumas bibliotecas de criptografia e drivers podem incluir extensões nativas. Nesses casos, você pode exigir instalação externa, distribuir os binários ao lado do .pyz ou escolher outro formato de empacotamento. Também precisa considerar arquitetura, sistema operacional e versão do Python.

Arquivos de dados e importlib.resources

Não monte caminhos com __file__ presumindo que tudo é um arquivo comum. Recursos dentro do ZIP podem não existir como caminhos reais.

from importlib.resources import files

texto = (
    files('meu_app.dados')
    .joinpath('config.json')
    .read_text(encoding='utf-8')
)

Quando uma API exige um caminho físico, use as_file() para obter um contexto temporário. O artigo de importlib.resources mostra esses padrões.

Verificar o interpretador gravado

zipapp.get_interpreter() lê o shebang de um arquivo.

import zipapp

interpretador = zipapp.get_interpreter('dist/meu_app.pyz')
print(interpretador)

Na CLI, python -m zipapp arquivo.pyz --info oferece diagnóstico equivalente. Use isso em pipelines para confirmar que o pacote final aponta ao interpretador esperado.

Copiar e alterar um arquivo existente

create_archive() também copia um .pyz existente para outro destino e pode mudar o shebang.

zipapp.create_archive(
    'app-antigo.pyz',
    'app-novo.pyz',
    interpreter='/usr/bin/env python3',
)

Não é permitido usar o mesmo caminho como origem e destino. Para substituição segura, escreva em arquivo temporário, valide o resultado, sincronize e então faça uma troca atômica.

Não sobrescreva em memória sem proteção

A documentação mostra que um arquivo pode ser copiado para BytesIO e gravado novamente, mas alerta que uma falha pode destruir o original. Em produção, prefira um novo arquivo e os.replace().

import os
import zipapp

novo = 'app.pyz.novo'
zipapp.create_archive('app.pyz', novo, '/usr/bin/env python3')
validar(novo)
os.replace(novo, 'app.pyz')

Reprodutibilidade

Um build repetível exige mais que o mesmo código. Controle versões do Python, dependências, arquivos incluídos, permissões, timestamps e ordem. Registre o hash final.

import hashlib
from pathlib import Path

conteudo = Path('dist/app.pyz').read_bytes()
print(hashlib.sha256(conteudo).hexdigest())

Ferramentas como compileall no Python e py_compile ajudam a verificar sintaxe, mas pré-compilar .pyc não elimina requisitos de compatibilidade.

Segurança da cadeia de distribuição

Um .pyz é código executável, não um formato seguro por natureza. Assine ou publique hashes por canal confiável, restrinja quem produz releases e não aceite arquivos desconhecidos para execução.

O ZIP pode ser inspecionado por ferramentas comuns. Nunca inclua segredos pensando que o empacotamento os esconde. Variáveis de ambiente, cofres de segredo e credenciais temporárias continuam sendo escolhas melhores.

Compatibilidade entre versões

O arquivo precisa ser compatível com o Python instalado. Sintaxe nova, APIs recentes e dependências podem falhar em versões anteriores. Defina uma versão mínima e teste em uma matriz de ambientes.

O shebang não oferece uma forma de expressar “Python X.Y ou superior”. Ele aponta para um comando. A validação de versão deve ocorrer no próprio programa quando necessário.

import sys

if sys.version_info < (3, 11):
    raise SystemExit('Python 3.11 ou superior é necessário')

Quando usar zipapp

Use zipapp quando a aplicação é predominantemente Python, o público já possui interpretador compatível e um único arquivo simplifica a entrega. É excelente para ferramentas internas e utilitários de automação.

Evite-o quando você precisa incluir o próprio Python, extensões C complexas, recursos que exigem caminhos físicos permanentes ou uma experiência de instalação nativa. Nesses casos, wheels, containers ou empacotadores de executáveis podem ser melhores.

Testar o artefato final

Não valide apenas o diretório-fonte. Execute o arquivo gerado em um ambiente limpo:

python dist/meu_app.pyz --version
python dist/meu_app.pyz diagnostico

Teste ausência de dependências globais, encoding, caminhos, recursos, argumentos, saída, erros e código de retorno. O guia sobre pydoc no Python também ajuda a verificar documentação acessível no pacote.

Erros frequentes

  • Esquecer __main__.py ou o parâmetro main.
  • Empacotar segredos e arquivos de desenvolvimento.
  • Presumir que extensões C funcionam dentro do ZIP.
  • Usar __file__ para todos os recursos.
  • Escolher shebang incompatível com o destino.
  • Sobrescrever o original sem troca atômica.
  • Testar apenas no computador de build.

Boas práticas

  • Construa em diretório limpo e descartável.
  • Fixe dependências e registre hashes.
  • Use filtro para excluir artefatos e segredos.
  • Acesse dados com importlib.resources.
  • Teste o .pyz em ambientes limpos.
  • Documente a versão mínima do Python.
  • Distribua por canal confiável.

Conclusão

O zipapp no Python transforma uma árvore de código em uma aplicação executável de arquivo único. Com entry point, shebang, filtros e dependências puramente Python, ele oferece uma distribuição simples e transparente.

A ferramenta não elimina o interpretador nem resolve binários nativos. Planeje compatibilidade, recursos, segurança e testes do artefato final. Consulte a documentação oficial do zipapp e a documentação do zipimport.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Editor de código representando autocompletar em REPL com rlcompleter no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    rlcompleter no Python: autocompletar REPL

    Aprenda rlcompleter no Python para adicionar autocompletar a REPLs, consoles e editores, controlar namespaces e evitar efeitos colaterais.

    Ler mais

    Tempo de leitura: 6 minutos
    13/08/2026
    Janela de terminal representando console interativo criado com cmd no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    cmd no Python: crie consoles interativos

    Aprenda cmd no Python para criar consoles interativos com comandos, ajuda, histórico, autocompletar, testes e controle seguro de ações.

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Terminal interativo representando um REPL customizado com o módulo code no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    code no Python: crie um REPL customizado

    Aprenda o módulo code no Python para criar REPLs customizados, controlar namespaces, prompts, saída, blocos incompletos e encerramento seguro.

    Ler mais

    Tempo de leitura: 6 minutos
    12/08/2026
    Código de aplicação web representando WSGI com wsgiref no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    wsgiref no Python: aplicações WSGI

    Aprenda wsgiref no Python para criar e validar aplicações WSGI, testar environ, headers, rotas e servidores locais sem usar em

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Protocolo seguro na internet representando preparação Unicode com stringprep no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    stringprep no Python: prepare Unicode

    Aprenda stringprep no Python para aplicar tabelas do RFC 3454, mapear Unicode, bloquear caracteres proibidos e validar regras bidirecionais.

    Ler mais

    Tempo de leitura: 7 minutos
    12/08/2026
    Rede de conexões representando I/O não bloqueante com selectors no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    selectors no Python: I/O não bloqueante

    Aprenda selectors no Python para monitorar vários sockets, eventos de leitura e escrita, timeouts e conexões não bloqueantes com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    11/08/2026