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.pyConviene 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.pyzLa opción -o define el archivo de salida. Después puedes iniciar la aplicación con:
python mi_app.pyzEn 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.pyzLa 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.pyzLa 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.







