zipimport en Python: importa desde ZIP

Publicado el: 14/08/2026
Tempo de leitura: 5 minutos
Archivadores organizados que representan módulos importados directamente desde archivos ZIP con zipimport en Python

El módulo zipimport en Python permite que el sistema de imports cargue módulos y paquetes directamente desde archivos ZIP. La mayoría de las aplicaciones no necesita instanciarlo manualmente: cuando una ruta ZIP aparece en sys.path, Python selecciona automáticamente un zipimporter.

Esta capacidad sirve para distribuir colecciones de módulos en un solo archivo, cargar plugins empaquetados, reducir miles de archivos pequeños y comprender aplicaciones .pyz. Importar desde ZIP no vuelve seguro el código externo. El módulo se ejecuta en el proceso actual con los mismos privilegios de la aplicación.

Cómo funciona la importación desde ZIP

Una entrada de sys.path suele apuntar a un directorio, pero también puede nombrar un ZIP. El importador busca archivos .py y .pyc respetando la estructura de paquetes.

import sys

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

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

No necesitas escribir import zipimport en este caso. El mecanismo de imports elige el finder apropiado.

Estructura de paquetes

Los paquetes tradicionales conservan su estructura normal, incluyendo __init__.py cuando corresponda.

plugins.zip
├── mi_plugin/
│   ├── __init__.py
│   ├── comandos.py
│   └── validacion.py
└── utilidad.py

Después de añadir el ZIP, instrucciones como from mi_plugin import comandos siguen las reglas habituales.

Usa un subdirectorio interno como raíz

La entrada puede apuntar a una carpeta dentro del archivo:

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

Solo lib/ se trata como raíz de imports. Esto ayuda cuando el ZIP contiene documentación, recursos y metadatos además del código.

Instancia zipimporter directamente

Herramientas de diagnóstico y loaders personalizados pueden crear zipimport.zipimporter.

from zipimport import zipimporter, ZipImportError

try:
    importador = zipimporter("plugins.zip")
except ZipImportError as error:
    print(f"Archivo inválido: {error}")
else:
    spec = importador.find_spec("mi_plugin")
    print(spec)

El constructor acepta el archivo completo o un prefijo interno como plugins.zip/lib. Una ruta inválida genera ZipImportError, también subclase de ImportError.

Prefiere find_spec

Los métodos antiguos fueron eliminados. Usa find_spec(), que devuelve un ModuleSpec compatible con importlib.

spec = importador.find_spec("mi_plugin.comandos")
if spec is None:
    raise ModuleNotFoundError("Plugin no encontrado")

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

En código normal, una instrucción import sigue siendo más sencilla.

Lee fuente sin ejecutar

get_source() devuelve el texto fuente cuando está presente.

fuente = importador.get_source("mi_plugin")
if fuente is not None:
    print(fuente[:200])

Esto evita ejecutar el módulo, pero la fuente continúa siendo dato no confiable. Limita su tamaño y no la publiques sin autorización.

Para listar clases y funciones sin importar, consulta pyclbr en Python.

Obtén el objeto de código

get_code() devuelve el objeto de código del módulo.

objeto = importador.get_code("mi_plugin")
print(objeto.co_filename)

Ejecutarlo con exec() tiene los mismos riesgos que importar. No es un sandbox.

Lee datos auxiliares

get_data() devuelve bytes de una ruta dentro del archivo.

datos = importador.get_data(
    "plugins.zip/mi_plugin/config.json"
)

Para recursos de paquetes, importlib.resources ofrece una interfaz más estructurada. Consulta importlib.resources en Python.

Inspecciona nombre y tipo

get_filename() devuelve el valor que tendría __file__. is_package() informa si el nombre representa un paquete.

print(importador.get_filename("mi_plugin"))
print(importador.is_package("mi_plugin"))

Son útiles para navegadores, validadores de plugins y diagnósticos.

Limitación de extensiones nativas

El importador carga fuente y bytecode Python, pero no extensiones dinámicas .so o .pyd directamente. El loader del sistema operativo necesita binarios como archivos reales.

Instala las dependencias nativas o extrae binarios verificados a un directorio controlado. La guía de zipapp en Python explica la misma limitación.

Fuente frente a bytecode

Si el ZIP solo contiene .py, Python compila durante el import, pero no modifica el archivo para añadir .pyc. Nuevos procesos pueden repetir ese trabajo.

El bytecode incluido debe coincidir con el intérprete. El formato cambia entre versiones, por lo que la fuente suele ser más portable. Un .pyc no es cifrado.

Crea el ZIP

from pathlib import Path
from zipfile import ZipFile, ZIP_DEFLATED

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

Excluye caches, artefactos, archivos de entorno, claves y credenciales. Normaliza las rutas y valida el resultado.

Sistemas de plugins empaquetados

Un servicio puede aceptar solo ZIPs firmados en un directorio aprobado, verificar hashes y cargar un entry point conocido. No debe ejecutar todos los módulos descubiertos.

from importlib import import_module

PERMITIDOS = {"informes", "exportacion"}

nombre = validar_nombre()
if nombre not in PERMITIDOS:
    raise PermissionError("Plugin no autorizado")

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

Una allowlist reduce errores, pero no aísla código hostil. Ejecuta plugins de terceros en otro proceso o contenedor.

Colisiones y orden de sys.path

Insertar el ZIP en la posición cero puede sombrear módulos confiables con el mismo nombre. Un json.py empaquetado podría sustituir la biblioteca estándar esperada.

Usa namespaces propios, evita poner archivos no confiables primero y registra el origen. Consulta site en Python y pkgutil en Python.

Cache del importador

invalidate_caches() limpia el listado interno.

importador.invalidate_caches()

Si el archivo cambia durante la ejecución, invalida caches y evita reemplazos concurrentes. Es mejor publicar nombres versionados e inmutables y reiniciar workers.

Actualizaciones atómicas

No edites el ZIP en el lugar mientras otros procesos importan. Crea uno nuevo, verifica integridad y firma, sincroniza la escritura y reemplaza la ruta de forma atómica. Los módulos ya presentes en sys.modules siguen cargados.

ZIP64 y tamaño

Las versiones actuales soportan ZIP64, pero archivos enormes aumentan tiempo de apertura, memoria y riesgo de denegación de servicio. Define límites de tamaño y entradas.

Seguridad

  • Importar ejecuta código con privilegios del proceso.
  • Verifica editor, firma y hash.
  • Restringe rutas y nombres calificados.
  • No importes directamente uploads arbitrarios.
  • Evita sombrear módulos confiables.
  • Limita tamaño, entradas y profundidad.
  • Aísla plugins no confiables.
  • Registra versión y entry point.

Pruebas

Prueba paquetes, subpaquetes, archivos solo con fuente, solo con bytecode, prefijos internos, ZIP corrupto, comentarios, ZIP64 y colisiones. Verifica todas las versiones y plataformas objetivo.

Confirma que dependencias nativas fallen con un mensaje claro y que el sistema no use un módulo inesperado instalado en otra ruta.

Conclusión

zipimport en Python integra archivos ZIP con el mecanismo estándar de imports y permite cargar módulos sin extracción. Ofrece acceso a specs, fuente, objetos de código, datos, estado de paquete y nombres de archivo.

Úsalo con políticas claras de origen, rutas e aislamiento. Consulta la documentación oficial de zipimport y la PEP 273 sobre imports desde ZIP.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Diagrama de directorios que representa rutas site-packages y configuración del módulo site en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    site en Python: entiende las rutas

    Aprende el módulo site en Python para entender site-packages, user site, archivos .pth, sitecustomize, usercustomize y opciones de inicio.

    Ler mais

    Tempo de leitura: 7 minutos
    14/08/2026
    Icono de instalador que representa el bootstrap offline de pip con ensurepip en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ensurepip en Python: restaura pip

    Aprende ensurepip en Python para instalar o restaurar pip sin internet, elegir entorno, scripts, upgrade y evitar conflictos con el

    Ler mais

    Tempo de leitura: 6 minutos
    14/08/2026
    Paquete de software que representa metadatos consultados con importlib.metadata en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    importlib.metadata en Python: paquetes

    Aprende importlib.metadata en Python para consultar versiones, dependencias, archivos, metadatos y entry points de paquetes instalados.

    Ler mais

    Tempo de leitura: 6 minutos
    14/08/2026
    Código en ejecución que representa módulos y rutas ejecutados con runpy en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    runpy en Python: ejecuta módulos

    Aprende runpy en Python para ejecutar módulos, scripts, directorios y archivos ZIP, controlar namespaces y evitar problemas de seguridad y

    Ler mais

    Tempo de leitura: 6 minutos
    13/08/2026
    Paquete de software que representa descubrimiento de módulos con pkgutil en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pkgutil en Python: descubre paquetes

    Aprende pkgutil en Python para descubrir módulos, recorrer paquetes, resolver objetos, extender rutas y acceder a recursos con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    13/08/2026
    Red de código binario que representa el grafo de imports analizado con modulefinder en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    modulefinder en Python: analiza imports

    Aprende modulefinder en Python para mapear imports, detectar módulos ausentes, personalizar rutas y auditar dependencias con límites claros.

    Ler mais

    Tempo de leitura: 6 minutos
    13/08/2026