zipapp en Python: crea apps ejecutables

Publicado el: 01/09/2026
Tempo de leitura: 5 minutos
Aplicación Python empaquetada como archivo ejecutable con zipapp

El módulo zipapp permite empaquetar una aplicación Python en un único archivo ejecutable, normalmente con extensión .pyz. El formato utiliza un archivo ZIP común que contiene un punto de entrada llamado __main__.py. Es una alternativa práctica para herramientas de línea de comandos, utilidades internas, proyectos educativos y entornos controlados donde Python ya está instalado.

Como zipapp forma parte de la biblioteca estándar, no necesitas instalar una herramienta externa para el flujo básico. No reemplaza a wheels, contenedores o generadores de ejecutables en todos los escenarios, pero ofrece una solución sencilla cuando el proyecto está escrito principalmente en Python puro.

Cómo funciona un archivo pyz

Un archivo .pyz es un ZIP que Python puede ejecutar directamente. El intérprete abre el archivo, busca __main__.py y lo ejecuta como entrada de la aplicación. Dentro pueden existir paquetes, módulos y recursos compatibles con importación desde ZIP.

mi_app/
├── __main__.py
├── cli.py
└── utilidades.py

Conviene mantener __main__.py pequeño. Lo ideal es importar una función principal y delegar la ejecución, lo que facilita pruebas y separa la interfaz de línea de comandos de la lógica de negocio.

from cli import main

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

Crea tu primer zipapp

Con la carpeta preparada, ejecuta:

python -m zipapp mi_app -o mi_app.pyz

La opción -o define el archivo de salida. Después puedes iniciar la aplicación con:

python mi_app.pyz

En sistemas Unix también puedes añadir una línea de intérprete y convertir el archivo en ejecutable:

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

La opción -p escribe el shebang. En Windows normalmente se usa python archivo.pyz, salvo que exista una asociación configurada.

Define el punto de entrada

Si la carpeta no contiene __main__.py, utiliza -m con el formato modulo:funcion:

python -m zipapp mi_app -m "cli:main" -o herramienta.pyz

La función indicada debe ser importable y no requerir argumentos posicionales obligatorios. El punto de entrada generado la invoca automáticamente.

Usa la API de Python

En scripts de build y pipelines de integración continua puedes usar zipapp.create_archive():

from zipapp import create_archive

create_archive(
    "mi_app",
    target="dist/mi_app.pyz",
    interpreter="/usr/bin/env python3",
    main="cli:main",
    compressed=True,
)

La API permite integrar empaquetado, validación, versionado y publicación del artefacto en un flujo automatizado y reproducible.

Gestiona dependencias

Las dependencias escritas en Python puro pueden instalarse dentro de una carpeta temporal antes de crear el archivo. Una técnica común utiliza pip --target:

python -m pip install -r requirements.txt --target build/app
cp -r src/* build/app/
python -m zipapp build/app -o dist/app.pyz -m "cli:main"

Este método no funciona bien con todos los paquetes que incluyen extensiones nativas. Archivos como .so o .pyd pueden necesitar una ubicación física y una compilación específica para cada plataforma. En esos casos conviene usar wheels, contenedores u otro formato.

Compatibilidad de versiones

El archivo no incluye el intérprete. La máquina de destino debe tener una versión compatible de Python. Si el proyecto utiliza sintaxis o APIs recientes, documenta claramente la versión mínima.

También debes probar diferencias entre sistemas operativos: rutas, permisos, comandos externos, señales y codificaciones pueden variar aunque el código sea Python puro.

Acceso correcto a recursos

No supongas que cada recurso interno tiene una ruta física normal. Para datos empaquetados, utiliza importlib.resources:

from importlib.resources import files

texto = files("mi_paquete").joinpath("plantilla.txt").read_text(
    encoding="utf-8"
)

Esta API funciona mejor con módulos cargados desde ZIP. Usar directamente Path(__file__).parent puede fallar cuando una biblioteca intenta abrir un archivo físico que no existe fuera del archivo comprimido.

Mantén la configuración fuera

No incluyas contraseñas, tokens o secretos dentro del .pyz. El archivo puede abrirse como cualquier ZIP. Utiliza variables de entorno, argumentos, almacenes de secretos o archivos externos con permisos adecuados.

Compresión

La compresión reduce el tamaño cuando hay muchos archivos de texto, aunque puede aumentar ligeramente el tiempo de inicio. Para utilidades pequeñas la diferencia suele ser mínima. Mide tamaño y rendimiento cuando ambos sean importantes.

Integridad y distribución

Un único artefacto simplifica descargas, despliegues y rollback. Genera un hash SHA-256 y publícalo en un canal confiable:

python -c "import hashlib, pathlib; p=pathlib.Path('app.pyz'); print(hashlib.sha256(p.read_bytes()).hexdigest())"

Si necesitas mayor garantía, firma digitalmente el archivo y verifica la firma antes de ejecutarlo.

Prueba el artefacto final

Las pruebas sobre el código fuente no son suficientes. Construye el archivo en CI y ejecuta smoke tests reales. El acceso a recursos, las importaciones dinámicas y algunas bibliotecas pueden comportarse de forma distinta dentro del ZIP.

Prueba la ayuda de la CLI, entradas inválidas, códigos de salida y cada versión de Python soportada. También conviene ejecutar el artefacto en los sistemas operativos objetivo.

Casos de uso

  • Herramientas internas de línea de comandos.
  • Scripts administrativos con varios módulos.
  • Aplicaciones Python puras para servidores controlados.
  • Utilidades educativas distribuidas como un solo archivo.
  • Artefactos simples en pipelines de automatización.

Cuándo elegir otro formato

Usa wheels cuando el usuario deba instalar un paquete en su entorno. Usa contenedores cuando necesites controlar sistema operativo y dependencias nativas. Usa un generador de ejecutables autónomos cuando el usuario no tenga Python. Zipapp funciona mejor cuando el intérprete ya existe.

Builds reproducibles

Fija versiones de dependencias, construye en una carpeta limpia, excluye cachés y archivos temporales y documenta el comando exacto. Los builds reproducibles facilitan depuración, auditoría y rollback.

Seguridad

Empaquetar no vuelve el código secreto ni confiable. Verifica el origen, el hash, la firma y las fuentes de dependencias. Nunca ejecutes archivos pyz no confiables con privilegios elevados.

Estructura mantenible

Conserva la lógica en módulos importables, limita el punto de entrada a la coordinación, valida entradas y devuelve códigos de salida útiles. Registra errores sin exponer secretos y mantén la CLI independiente de la lógica central.

Para seguir aprendiendo, consulta los artículos de Academify sobre importlib.resources en Python, entornos virtuales, argparse en Python y subprocess en Python.

Conclusión

zipapp convierte una aplicación Python en un único archivo ejecutable sin herramientas externas. Es especialmente útil para proyectos Python puros y entornos con un intérprete compatible. Con un punto de entrada claro, recursos bien gestionados, dependencias fijadas, configuración externa, verificación de integridad y pruebas del artefacto final, obtienes una distribución sencilla y confiable.

Fuentes externas

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python usado para componer funciones con functools.Placeholder
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    functools.Placeholder: huecos posicionales en partial

    Aprende functools.Placeholder en Python para dejar huecos posicionales en partial y crear APIs funcionales claras y reutilizables.

    Ler mais

    Tempo de leitura: 5 minutos
    31/08/2026
    Persona programando y analizando datos con Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    itertools.pairwise: compara elementos vecinos

    Aprende itertools.pairwise en Python para comparar elementos vecinos, detectar cambios, calcular diferencias y crear pipelines lazy claros.

    Ler mais

    Tempo de leitura: 4 minutos
    31/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    types.new_class en Python: clases dinámicas

    Aprende types.new_class en Python para generar clases dinámicas con metaclases, namespaces preparados, herencia y metadatos correctos.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    High-angle view of woman coding on a laptop, with a Python book nearby. Ideal for programming and tech content.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    partialmethod: crea métodos especializados en Python

    Aprende partialmethod en Python para métodos especializados con binding correcto, menos wrappers y APIs de dominio más claras.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    inspect.getmembers_static: atributos sin ejecutar

    Usa inspect.getmembers_static en Python para listar atributos sin ejecutar properties, descriptors ni resolución dinámica no deseada.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    DynamicClassAttribute: descriptors y acceso dinámico

    Entiende DynamicClassAttribute en Python, descriptors, acceso por clase e instancia, metaclases, Enum e introspección segura.

    Ler mais

    Tempo de leitura: 3 minutos
    30/08/2026