zipimport no Python: importe de ZIPs

Publicado em: 14/08/2026
Tempo de leitura: 6 minutos
Arquivadores organizados representando módulos importados diretamente de arquivos ZIP com zipimport no Python

O módulo zipimport no Python permite importar módulos e pacotes diretamente de arquivos ZIP. Na maioria das aplicações, você não precisa instanciá-lo manualmente: o mecanismo padrão de importação reconhece caminhos ZIP presentes em sys.path e usa zipimporter automaticamente.

Esse recurso é útil para distribuir coleções de módulos em um único arquivo, carregar plugins empacotados, reduzir a quantidade de pequenos arquivos e entender como aplicações .pyz funcionam. Entretanto, importar de ZIP não transforma código externo em seguro. O módulo importado é executado no processo atual com os mesmos privilégios da aplicação.

Como a importação por ZIP funciona

Um item de sys.path normalmente aponta para um diretório, mas também pode apontar para um arquivo ZIP. O importador procura arquivos .py e .pyc dentro do arquivo, respeitando a estrutura de pacotes.

import sys

sys.path.insert(0, "plugins.zip")
import meu_plugin

print(meu_plugin.__file__)
# plugins.zip/meu_plugin.py

Não é necessário escrever import zipimport para esse cenário. O sistema de imports seleciona o finder apropriado por meio dos hooks de caminho.

Estrutura de pacotes no arquivo

Pacotes tradicionais precisam manter sua estrutura, incluindo __init__.py quando aplicável.

plugins.zip
├── meu_plugin/
│   ├── __init__.py
│   ├── comandos.py
│   └── validacao.py
└── util.py

Depois de adicionar o ZIP ao caminho, você pode usar from meu_plugin import comandos. O arquivo deve preservar os nomes e diretórios esperados pelo sistema de importação.

Importe somente de um subdiretório

O caminho pode apontar para uma pasta interna do arquivo:

sys.path.insert(0, "pacote.zip/lib")
import biblioteca

Nesse caso, apenas lib/ é tratada como raiz de importação. Isso ajuda quando o ZIP inclui documentação, recursos, metadados e código em diretórios separados.

Use zipimporter diretamente

Para ferramentas de diagnóstico e loaders customizados, crie uma instância de zipimport.zipimporter.

from zipimport import zipimporter, ZipImportError

try:
    importer = zipimporter("plugins.zip")
except ZipImportError as erro:
    print(f"Arquivo inválido: {erro}")
else:
    spec = importer.find_spec("meu_plugin")
    print(spec)

O construtor aceita o arquivo completo ou um caminho interno, como plugins.zip/lib. Um arquivo inexistente ou inválido gera ZipImportError, que também é uma subclasse de ImportError.

Prefira find_spec

APIs antigas como find_module() e find_loader() foram removidas. Use find_spec(), que devolve um ModuleSpec compatível com importlib.

spec = importer.find_spec("meu_plugin.comandos")
if spec is None:
    raise ModuleNotFoundError("Plugin não encontrado")

modulo = __import__("meu_plugin.comandos", fromlist=["*"])

Na maior parte dos casos, ainda é melhor deixar a instrução import cuidar de todo o ciclo.

Leia código sem executar

get_source() retorna a fonte de um módulo quando ela está presente.

fonte = importer.get_source("meu_plugin")
if fonte is not None:
    print(fonte[:200])

Isso evita executar o módulo, mas não garante que o conteúdo seja confiável. Trate a fonte como dado externo, limite o tamanho e não a publique sem sanitização.

Para listar classes e funções sem importar, o guia de pyclbr no Python apresenta uma alternativa voltada a código-fonte Python.

Obtenha objetos de código

get_code() compila ou recupera o objeto de código correspondente.

objeto = importer.get_code("meu_plugin")
print(objeto.co_filename)

Executar esse objeto com exec() possui os mesmos riscos de importar o módulo. Não use essa API para tentar criar uma sandbox.

Leia arquivos auxiliares

get_data() devolve bytes de um caminho existente no arquivo.

conteudo = importer.get_data("plugins.zip/meu_plugin/config.json")

A montagem exata do caminho depende do arquivo e do prefixo do importador. Para recursos de pacotes, importlib.resources costuma oferecer uma interface mais estruturada. Veja o guia de importlib.resources no Python.

Descubra arquivo e tipo de módulo

get_filename() mostra o valor que seria usado em __file__. is_package() informa se o nome corresponde a pacote.

print(importer.get_filename("meu_plugin"))
print(importer.is_package("meu_plugin"))

Essas funções ajudam navegadores, diagnósticos e sistemas de plugins a validar a estrutura antes da importação.

Limitação das extensões nativas

O importador aceita código-fonte e bytecode Python, mas não carrega módulos dinâmicos como .so e .pyd diretamente do ZIP. O carregador do sistema operacional precisa acessar binários como arquivos reais.

Se uma dependência contém extensão C, distribua-a instalada no ambiente ou extraia-a de maneira controlada para um diretório compatível com a plataforma. O guia de zipapp no Python explica a mesma limitação em aplicações .pyz.

Fonte versus bytecode

Quando o ZIP contém somente .py, Python compila o código durante a importação, mas não modifica o arquivo ZIP para adicionar .pyc. Importações repetidas em processos novos podem ser mais lentas.

Você pode incluir bytecode criado pela versão correta do Python, mas o formato não é estável entre versões. Em distribuições portáteis, manter a fonte geralmente é mais seguro. Nunca trate .pyc como criptografia.

Crie o arquivo corretamente

Use zipfile para gerar o pacote:

from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED

with ZipFile("plugins.zip", "w", ZIP_DEFLATED) as zipf:
    for arquivo in Path("plugins").rglob("*.py"):
        zipf.write(arquivo, arquivo.relative_to("plugins"))

Normalize os caminhos, exclua caches e não inclua segredos, chaves privadas ou arquivos de ambiente. Para extração e validação segura, consulte zipfile no Python.

Plugins empacotados

Um sistema de plugins pode colocar arquivos ZIP em um diretório aprovado, verificar assinatura e hash, adicionar o caminho e importar um entry point conhecido. Não descubra nem execute qualquer módulo automaticamente.

from importlib import import_module

PERMITIDOS = {"relatorios", "exportacao"}

nome = validar_nome_solicitado()
if nome not in PERMITIDOS:
    raise PermissionError("Plugin não autorizado")

plugin = import_module(f"plugins.{nome}")

Uma allowlist reduz o risco, mas não substitui isolamento. Plugins de terceiros devem rodar em processo separado ou ambiente controlado.

Conflitos de nomes e ordem de sys.path

Inserir o ZIP na posição zero pode sobrescrever módulos legítimos com o mesmo nome. Um arquivo chamado json.py, por exemplo, pode sombrear a biblioteca padrão.

Use namespaces exclusivos, prefira adicionar o caminho após entradas confiáveis e registre de onde cada módulo foi carregado. Para investigar caminhos de runtime, veja site no Python e pkgutil no Python.

Cache do importador

invalidate_caches() limpa informações internas sobre os arquivos do ZIP.

importer.invalidate_caches()

Se o arquivo é substituído durante a execução, invalide caches e evite trocas concorrentes. Uma estratégia mais segura é publicar um arquivo imutável com nome versionado e reiniciar os workers.

Atualizações atômicas

Não edite o ZIP no lugar enquanto outros threads ou processos importam. Crie um novo arquivo em localização temporária, valide sua integridade, sincronize a gravação e faça uma substituição atômica. Mesmo assim, módulos já presentes em sys.modules continuam carregados.

ZIP64 e arquivos grandes

Versões atuais suportam ZIP64, permitindo arquivos maiores e grande quantidade de entradas. Isso não significa que arquivos enormes sejam ideais. Um índice grande aumenta tempo de abertura, consumo de memória e superfície para ataques de negação de serviço.

Segurança

  • Importar executa código com os privilégios do processo.
  • Valide origem, assinatura e hash do arquivo.
  • Restrinja caminhos e nomes de módulos.
  • Não aceite ZIP enviado por usuário para importação direta.
  • Evite colisões em sys.path.
  • Limite tamanho, entradas e profundidade.
  • Execute plugins não confiáveis em isolamento real.
  • Registre arquivo, versão e módulo carregado.

Testes importantes

Teste pacotes, subpacotes, módulos apenas com fonte, módulos apenas com bytecode, caminhos internos, arquivo corrompido, comentários no ZIP, ZIP64 e colisões de nomes. Verifique também comportamento em Windows e Linux.

Confirme que dependências nativas produzem uma mensagem clara e que o sistema não cai para um módulo inesperado instalado fora do arquivo.

Conclusão

O zipimport no Python integra arquivos ZIP ao mecanismo padrão de imports e permite distribuir módulos Python em um único contêiner. Ele oferece acesso a specs, fonte, bytecode, dados e metadados do módulo sem exigir extração prévia.

Use o recurso com políticas explícitas de origem, caminhos e isolamento. Consulte a documentação oficial do zipimport e a PEP 273 sobre imports de ZIP.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Diagrama de diretórios representando caminhos site-packages e configuração do módulo site no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    site no Python: entenda os caminhos

    Aprenda o módulo site no Python para entender site-packages, user site, arquivos .pth, sitecustomize, usercustomize e opções de inicialização.

    Ler mais

    Tempo de leitura: 8 minutos
    14/08/2026
    Ícone de instalador representando o bootstrap offline do pip com ensurepip no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ensurepip no Python: reinstale o pip

    Aprenda ensurepip no Python para instalar ou restaurar o pip offline, escolher ambiente, scripts, upgrade e evitar conflitos com o

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026
    Caixa de software representando metadados de pacotes consultados com importlib.metadata no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    importlib.metadata no Python: pacotes

    Aprenda importlib.metadata no Python para consultar versões, dependências, arquivos, metadados e entry points de pacotes instalados.

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026
    Código em execução representando módulos e caminhos executados com runpy no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    runpy no Python: execute módulos

    Aprenda runpy no Python para executar módulos, scripts, diretórios e arquivos ZIP, controlar namespaces e evitar problemas de segurança e

    Ler mais

    Tempo de leitura: 6 minutos
    13/08/2026
    Pacote de software representando descoberta de módulos com pkgutil no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pkgutil no Python: descubra pacotes

    Aprenda pkgutil no Python para descobrir módulos, percorrer pacotes, resolver objetos, estender caminhos e acessar recursos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    13/08/2026
    Rede de código binário representando o grafo de imports analisado com modulefinder no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    modulefinder no Python: analise imports

    Aprenda modulefinder no Python para mapear imports, detectar módulos ausentes, personalizar caminhos e auditar dependências com limites claros.

    Ler mais

    Tempo de leitura: 7 minutos
    13/08/2026