zipapp no Python: crie arquivos .pyz

Publicado em: 27/08/2026
Tempo de leitura: 8 minutos
Color-coded office binders organized neatly in a storage shelf, featuring labels and a striking red binder.

O módulo zipapp cria aplicações Python executáveis em um único arquivo ZIP, normalmente com extensão .pyz. O interpretador consegue adicionar o arquivo ao sys.path e executar seu __main__.py. Esse formato é útil para ferramentas internas, scripts de automação, utilitários de linha de comando, protótipos e distribuição em ambientes que já possuem uma versão compatível do Python.

Um zipapp não é um executável nativo independente. Ele não inclui automaticamente o interpretador, não resolve todas as dependências e não transforma extensões compiladas em arquivos importáveis dentro do ZIP. Para distribuição pública, desktop ou ambientes sem Python, ferramentas de empacotamento completas podem ser mais adequadas.

Estrutura mínima

Uma aplicação ZIP precisa de um arquivo __main__.py na raiz.

meu_app/
├── __main__.py
└── pacote/
    ├── __init__.py
    └── cli.py

O conteúdo de __main__.py inicia a aplicação.

from pacote.cli import main

if __name__ == "__main__":
    raise SystemExit(main())

Esse padrão permite testar main() separadamente e propagar um código de saída.

Crie pela linha de comando

Use o módulo com -m.

python -m zipapp meu_app -o meu_app.pyz

Depois execute:

python meu_app.pyz --help

O Python trata o arquivo como um diretório importável e executa seu entry point.

Crie pela API

A função zipapp.create_archive() permite automatizar o build.

from zipapp import create_archive

create_archive(
    "meu_app",
    target="dist/meu_app.pyz",
)

Crie o diretório de destino antes ou use pathlib para organizar o pipeline.

Entry point com main

Quando o diretório não possui __main__.py, você pode indicar um entry point no formato pacote.modulo:funcao.

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

O zipapp gera um __main__.py que importa e chama a função.

Requisitos da função principal

A função deve ser importável e chamável sem argumentos, a menos que ela própria leia sys.argv. Um padrão claro:

def main():
    argumentos = parser.parse_args()
    executar(argumentos)
    return 0

Não coloque toda a lógica no import do módulo. Imports devem configurar definições, não executar o programa.

Shebang e interpreter

A opção --python ou o parâmetro interpreter adiciona uma linha de interpreter ao início do arquivo.

python -m zipapp meu_app \
  --python "/usr/bin/env python3" \
  -o meu_app.pyz
chmod +x meu_app.pyz
./meu_app.pyz

Isso funciona em sistemas compatíveis com shebang. No Windows, normalmente execute com python meu_app.pyz ou associe a extensão.

Escolha de versão

Um shebang genérico como python3 pode encontrar versões diferentes em cada máquina. Se o código exige uma versão mínima, valide no início.

import sys

if sys.version_info < (3, 12):
    raise SystemExit("Python 3.12 ou superior é necessário")

Também documente a versão testada.

Compressão

A opção --compress ou compressed=True comprime arquivos dentro do archive.

create_archive(
    "meu_app",
    target="dist/meu_app.pyz",
    compressed=True,
)

A compressão reduz tamanho, mas aumenta CPU durante build e leitura. Para código pequeno, a diferença pode ser mínima.

Aplicações já compactadas

create_archive() também pode copiar ou ajustar um archive existente em determinados fluxos. Não use essa capacidade como editor genérico de ZIP sem entender o comportamento.

Recrie a aplicação a partir de uma fonte limpa para builds reproduzíveis.

Dependências Python puras

Pacotes escritos apenas em Python podem ser copiados para o diretório antes do build.

python -m pip install \
  --target build/app \
  --requirement requirements.txt
cp -r src/meu_pacote build/app/
python -m zipapp build/app -o dist/app.pyz

Use um ambiente de build isolado e versões fixadas.

Extensões nativas

Módulos compilados como .so e .pyd normalmente não podem ser importados diretamente de dentro do ZIP, porque o loader do sistema precisa de um arquivo real.

Se uma dependência contém código nativo, mantenha-a instalada fora do zipapp, extraia-a de forma controlada ou escolha outra ferramenta de distribuição.

Descubra dependências nativas

Não confie apenas no nome do pacote. Inspecione a wheel e teste em um ambiente limpo.

Dependências transitivas podem introduzir extensões nativas mesmo quando o pacote principal parece puro.

Recursos do pacote

Código dentro do ZIP não deve presumir que __file__ aponta para um arquivo normal acessível por APIs do sistema.

Use importlib.resources para ler templates, dados e arquivos empacotados.

from importlib.resources import files

texto = (
    files("meu_pacote")
    .joinpath("dados/config_padrao.json")
    .read_text(encoding="utf-8")
)

Recursos que exigem path real

Algumas bibliotecas exigem um pathname. importlib.resources.as_file() pode materializar temporariamente um recurso quando suportado.

Use um context manager e não guarde o path depois da saída.

Arquivos graváveis

O conteúdo do zipapp deve ser tratado como somente leitura. Não grave configuração, cache ou banco ao lado dos módulos internos.

Escolha diretórios de usuário, temporários ou de dados da aplicação e permita configuração explícita.

Diretório atual

Não presuma que o processo começa no diretório do archive. Path.cwd() depende de onde o usuário executou o comando.

Use caminhos absolutos configurados ou recursos internos.

Imports absolutos

Organize a aplicação como pacote e use imports absolutos. Imports relativos frágeis e módulos com nomes iguais aos da biblioteca padrão causam conflitos.

Teste o arquivo final, não apenas a árvore de fontes.

Namespace packages

Namespace packages podem funcionar, mas combinações com partes externas e loaders diferentes exigem testes.

Para uma ferramenta compacta, um pacote normal costuma ser mais previsível.

sys.path

Durante a execução, o archive aparece no caminho de imports. A ordem exata pode interagir com pacotes instalados externamente.

Não dependa de shadowing acidental. Use nomes de pacote únicos e valide versões de dependências.

Conflito com ambiente externo

Se uma dependência não está embutida, o zipapp pode importar uma versão instalada no ambiente do usuário.

Isso reduz o isolamento. Faça validação de versão ou distribua um ambiente virtual junto com instruções claras.

Zipapp e venv

Uma estratégia interna é criar um venv com dependências nativas e executar o .pyz com o Python desse ambiente.

O zipapp contém o código da aplicação; o venv fornece runtime e bibliotecas externas.

Zipapp e pipx

Ferramentas como pipx instalam aplicações Python em ambientes isolados. Para distribuição convencional de CLI, um pacote com entry point pode ser mais fácil de atualizar que um archive manual.

Escolha zipapp quando o arquivo único realmente simplifica a operação.

Metadados de versão

Inclua uma constante ou metadata acessível pelo comando --version.

__version__ = "1.4.0"

Também pode gravar um arquivo de manifest dentro do archive com commit, data e versão de build.

Build reproduzível

ZIPs armazenam timestamps e ordem de entradas, o que pode tornar hashes diferentes. Para reproducibility, controle timestamps, ordene arquivos e fixe dependências.

O zipapp básico pode não atender todos os requisitos de build determinístico sem uma etapa adicional.

Filtro de arquivos

A API aceita um filtro para decidir quais caminhos entram.

def incluir(caminho):
    partes = set(caminho.parts)
    return not partes.intersection({"__pycache__", ".git", "tests"})

create_archive("build/app", "dist/app.pyz", filter=incluir)

Não exclua arquivos necessários por engano. Teste a aplicação final em um diretório limpo.

Não inclua segredos

Um zipapp é apenas um ZIP e pode ser aberto facilmente. Nunca coloque senhas, tokens, chaves privadas ou credenciais dentro dele.

Leia segredos de um secret manager, ambiente controlado ou arquivo externo protegido.

Assinatura e checksum

Distribua um hash ou assinatura para verificar integridade. O Python não valida automaticamente uma assinatura do zipapp antes de executar.

O processo de distribuição precisa verificar o arquivo antes de invocar o interpretador.

Código não confiável

Executar um .pyz executa código Python com as permissões do usuário. Não baixe e execute archives desconhecidos.

Use HTTPS, assinatura, origem confiável e menor privilégio.

Atualização

Um arquivo único facilita substituição, mas a atualização deve ser atômica. Baixe para um nome temporário, valide e use os.replace().

Não sobrescreva o arquivo enquanto uma verificação ainda está em andamento.

Rollback

Mantenha a versão anterior até o novo arquivo passar por um teste rápido. Um symlink ou launcher pode selecionar a versão ativa.

Não misture migrations irreversíveis com atualização sem plano de rollback.

Execução em containers

Um zipapp pode reduzir arquivos de aplicação em uma imagem, mas ainda precisa do runtime e dependências.

Containers já fornecem isolamento e layers; avalie se o archive realmente agrega valor.

Argumentos e códigos de saída

Use argparse e retorne códigos consistentes. raise SystemExit(main()) preserva o status.

Escreva dados normais em stdout e erros em stderr para integração com shell.

Logging

Não escreva logs dentro do ZIP. Configure stderr, arquivo externo ou logging estruturado.

Inclua versão do archive no início do processo para diagnóstico.

Testes

Crie o archive em CI e execute comandos reais em um ambiente limpo. Teste ajuda, versão, erro de dependência, recurso interno, código de saída, paths com espaços, Windows e POSIX.

Compare o comportamento da fonte e do .pyz.

Erros comuns

Os erros mais frequentes são esquecer __main__.py, incluir extensão nativa dentro do ZIP, usar __file__ como path normal, gravar dentro do archive, depender de pacote externo em versão desconhecida, incluir segredos, não testar o artefato e confundir zipapp com executável autossuficiente.

Conclusão

zipapp oferece uma forma simples de empacotar aplicações Python puras em um arquivo executável pelo interpretador. Organize um entry point limpo, use importlib.resources, fixe dependências, trate o archive como somente leitura e teste no ambiente final.

Consulte a documentação oficial de zipapp e o artigo sobre sysconfig no Python para compreender o runtime de destino.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sysconfig no Python: caminhos e build

    Aprenda sysconfig no Python para descobrir paths, schemes, headers, flags de build, ABI, extensões nativas e detalhes de ambientes virtuais.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    marshal no Python: formato interno

    Aprenda marshal no Python para objetos internos e bytecode, entenda versões, allow_code, limites, caches e riscos de dados não confiáveis.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    A close-up view of fresh, green cucumbers ready for pickling and preservation in Estonia.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    copyreg no Python: personalize o pickle

    Aprenda copyreg no Python para personalizar pickle, registrar redutores, versionar estado, evitar conflitos globais e serializar com segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    reprlib no Python: representações seguras

    Aprenda reprlib no Python para resumir listas, strings e objetos recursivos, limitar logs e criar representações seguras e legíveis.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    graphlib no Python: ordenação topológica

    Aprenda graphlib no Python para ordenar dependências, detectar ciclos, executar tarefas prontas em paralelo e criar pipelines seguros.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    weakref: evite reter objetos em caches

    Aprenda weakref no Python para referências fracas, caches, WeakSet, WeakMethod, finalize, callbacks e prevenção de retenção acidental.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026