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.jsonCom essa estrutura, o comando abaixo gera meu_app.pyz:
python -m zipapp meu_appDepois:
python meu_app.pyzO 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.pyzA 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.pyzO 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.pyzA 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.pyzFixe 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 diagnosticoTeste 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__.pyou o parâmetromain. - 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
.pyzem 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.







