Convertir un script de Python en un archivo .exe permite ejecutar una aplicación en Windows sin pedir al usuario que instale Python manualmente. PyInstaller analiza imports, reúne el intérprete y las dependencias y genera una carpeta distribuible o un único ejecutable. No compila el programa a código nativo ni protege el código frente a inspección; su objetivo principal es empaquetar.
Antes de comenzar, revisa la guía de entornos virtuales, el tutorial para instalar bibliotecas con pip, el artículo sobre pathlib, la guía de manejo de excepciones y el tutorial para crear una aplicación con Tkinter.
Las referencias externas principales son la documentación oficial de PyInstaller y la guía oficial de Python Packaging.
Crear un entorno limpio
mkdir mi_aplicacion
cd mi_aplicacion
python -m venv .venv
Activa el entorno. En PowerShell:
.venv\Scripts\Activate.ps1
Instala únicamente las dependencias necesarias:
python -m pip install --upgrade pip
python -m pip install pyinstaller
Un entorno limpio evita incluir paquetes irrelevantes y facilita reproducir la compilación.
Crear un script de prueba
def saludar(nombre):
return f"Hola, {nombre}"
if __name__ == "__main__":
nombre = input("Nombre: ").strip() or "Mundo"
print(saludar(nombre))
input("Pulsa Enter para salir")
Guárdalo como app.py y ejecútalo antes de empaquetar:
python app.py
Generar una carpeta distribuible
pyinstaller app.py
PyInstaller crea normalmente tres elementos:
build/
dist/
app.spec
El ejecutable y sus archivos estarán en dist/app/. La carpeta build contiene archivos temporales y puede eliminarse después.
Crear un único archivo
pyinstaller --onefile app.py
El resultado estará en dist/app.exe. El modo onefile es cómodo para distribuir, pero puede tardar más en iniciar porque extrae componentes temporalmente.
Aplicaciones sin consola
Para una interfaz Tkinter que no necesita terminal:
pyinstaller --onefile --windowed app.py
No utilices --windowed mientras todavía depuras errores, porque perderás mensajes de la consola. Durante el desarrollo es mejor conservarla.
Añadir un icono
pyinstaller --onefile --icon=icono.ico app.py
En Windows utiliza normalmente un archivo ICO válido con varias resoluciones. El icono del ejecutable no cambia automáticamente el icono de una ventana Tkinter.
Definir un nombre
pyinstaller --onefile --name MiHerramienta app.py
Evita caracteres problemáticos y nombres que puedan confundirse con componentes del sistema.
Incluir archivos de datos
Una aplicación puede necesitar imágenes, plantillas o JSON:
pyinstaller --onefile --add-data "datos.json;." app.py
En Windows, la separación habitual entre origen y destino es punto y coma. En otros sistemas puede utilizarse dos puntos. Consulta la documentación para la plataforma de compilación.
Localizar recursos en desarrollo y en el EXE
from pathlib import Path
import sys
def ruta_recurso(nombre):
if getattr(sys, "frozen", False):
base = Path(sys._MEIPASS)
else:
base = Path(__file__).resolve().parent
return base / nombre
ruta_datos = ruta_recurso("datos.json")
La ubicación temporal utilizada en onefile no es un lugar apropiado para guardar datos modificables.
Guardar datos del usuario
Utiliza una carpeta persistente, como el directorio del perfil:
import os
from pathlib import Path
base = Path(os.getenv("APPDATA", Path.home())) / "MiHerramienta"
base.mkdir(parents=True, exist_ok=True)
ruta_config = base / "config.json"
No intentes escribir junto al ejecutable si puede estar en una carpeta protegida.
Imports ocultos
Algunas bibliotecas cargan módulos dinámicamente y PyInstaller puede no detectarlos:
pyinstaller --onefile --hidden-import=paquete.modulo app.py
No añadas imports al azar. Revisa el traceback y la documentación de los hooks de PyInstaller.
Recopilar archivos de un paquete
pyinstaller --onefile --collect-all nombre_paquete app.py
Esta opción puede aumentar mucho el tamaño. Utilízala cuando el paquete necesite datos o submódulos que no se detectan automáticamente.
Trabajar con el archivo SPEC
Después de la primera ejecución aparece app.spec. Puedes editarlo para controlar datos, binaries, imports y opciones:
a = Analysis(
["app.py"],
datas=[("datos.json", ".")],
hiddenimports=[],
)
Vuelve a generar utilizando:
pyinstaller app.spec
Versionar el SPEC ayuda a reproducir compilaciones complejas.
Limpiar compilaciones anteriores
pyinstaller --clean --noconfirm app.spec
--clean elimina cachés de PyInstaller y --noconfirm reemplaza la carpeta de salida sin preguntar. Asegúrate de que dist no contenga archivos manuales importantes.
Probar en otro equipo
No basta con ejecutar el EXE en el ordenador donde fue creado. Prueba en una máquina limpia o una máquina virtual con la misma arquitectura y una versión compatible de Windows. Verifica inicio, archivos, rutas, permisos, red y cierre.
Compilar para cada sistema
PyInstaller no es un compilador cruzado general. Para crear un EXE de Windows, compila en Windows. Para macOS o Linux, crea el paquete en esos sistemas. Mantén scripts de compilación separados.
Archivos grandes
El ejecutable incluye Python y dependencias, por lo que puede ocupar decenas o cientos de megabytes. Elimina paquetes innecesarios, evita importar bibliotecas enormes para una función pequeña y compara onedir con onefile.
Antivirus y falsos positivos
Algunos ejecutables empaquetados pueden activar alertas heurísticas, especialmente si son nuevos, no están firmados o utilizan compresión. No intentes evadir antivirus. Distribuye desde un sitio confiable, publica hashes, firma el código cuando corresponda y envía falsos positivos al proveedor.
Firmar el ejecutable
La firma de código permite verificar editor e integridad. Requiere un certificado válido y herramientas de Windows. No elimina todas las advertencias inmediatamente, pero mejora la confianza y protege frente a modificaciones.
No guardar secretos dentro del EXE
Tokens, contraseñas y claves pueden extraerse. Utiliza variables de entorno, autenticación del usuario o un backend seguro. Empaquetar no cifra el código.
Crear un script de compilación
@echo off
call .venv\Scripts\activate.bat
pyinstaller --clean --noconfirm app.spec
if errorlevel 1 exit /b 1
certutil -hashfile dist\MiHerramienta.exe SHA256
Automatizar reduce diferencias entre compilaciones.
Registrar la versión
VERSION = "1.0.0"
Puedes incluirla en la interfaz y en metadatos de Windows mediante un archivo de versión. Mantén un registro de cambios y no reemplaces silenciosamente ejecutables publicados.
Errores frecuentes
Los problemas habituales son compilar desde un entorno lleno de paquetes, olvidar archivos de datos, usar rutas relativas al directorio actual, ocultar la consola demasiado pronto, guardar configuración en la carpeta temporal y esperar que el EXE funcione en cualquier sistema. También es común creer que PyInstaller protege el código.
Conclusión
PyInstaller permite distribuir scripts Python como ejecutables de Windows. Empieza con un entorno limpio, prueba el script, crea primero una versión onedir y después evalúa onefile. Gestiona recursos con rutas compatibles, utiliza un archivo SPEC y prueba en una máquina limpia. Para una distribución profesional, añade firma, hashes, versiones y un proceso de actualización seguro.





