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

    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026
    Código Python exibindo avisos controlados com catch_warnings
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    catch_warnings: capture warnings em testes Python

    Aprenda catch_warnings no Python para capturar, testar e controlar avisos com filtros específicos e segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código Python representando referências persistentes do pickle
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pickle persistent_id: serialize referências externas

    Aprenda pickle persistent_id no Python para serializar referências externas com IDs estáveis, validação, segurança e compatibilidade.

    Ler mais

    Tempo de leitura: 5 minutos
    07/10/2026
    Código binário representando buffers e memória no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    memoryview.count: conte valores sem copiar buffers

    Aprenda memoryview.count no Python para contar bytes e valores em buffers sem cópias, com formatos, limites e boas práticas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python com anotações de tipos
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    annotationlib: evite imports circulares em anotações

    Aprenda annotationlib no Python para ler anotações adiadas, evitar imports circulares e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 6 minutos
    06/10/2026
    Código Python em tela representando inspeção de módulos e pacotes
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    inspect.ispackage: identifique pacotes Python

    Aprenda inspect.ispackage no Python para identificar pacotes, explorar módulos e criar ferramentas de introspecção seguras.

    Ler mais

    Tempo de leitura: 5 minutos
    05/10/2026