Transformar una aplicación Python en un archivo EXE facilita su uso en equipos Windows donde el destinatario no desea abrir un terminal ni instalar manualmente todas las dependencias. PyInstaller analiza el programa, reúne el intérprete, módulos y archivos necesarios, y genera una distribución ejecutable. También permite asignar un icono personalizado, ocultar la consola en aplicaciones gráficas y añadir recursos como imágenes o archivos de configuración.
Antes de comenzar, revisa cómo convertir scripts en EXE, cómo utilizar entornos virtuales, cómo crear una aplicación con Tkinter, cómo trabajar con rutas y archivos y cómo instalar bibliotecas con pip.
El manual oficial de PyInstaller documenta instalación, opciones, archivos SPEC y solución de problemas. La documentación oficial de Pillow sobre ICO explica el formato utilizado por los iconos de Windows.
Qué hace PyInstaller
PyInstaller empaqueta la aplicación y sus dependencias. El usuario final puede ejecutar el resultado sin instalar Python por separado. Sin embargo, PyInstaller no es un compilador cruzado: para crear una aplicación de Windows debes construirla en Windows. Lo mismo se aplica a macOS y Linux.
Preparar un entorno limpio
python -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
python -m pip install pyinstaller
Instala dentro del entorno únicamente las dependencias necesarias para la aplicación. Un entorno lleno de paquetes no utilizados puede complicar el análisis y aumentar el tamaño final.
Probar el programa antes de empaquetar
python app.py
No uses PyInstaller para ocultar errores normales del programa. Confirma que la aplicación abre, encuentra sus recursos, maneja entradas inválidas y cierra correctamente.
Crear la primera distribución
pyinstaller app.py
El comando crea normalmente las carpetas build y dist, además de un archivo app.spec. Dentro de dist encontrarás la aplicación distribuible.
Modo de una sola carpeta
El modo predeterminado genera una carpeta con el ejecutable y las bibliotecas. Suele ser más fácil de diagnosticar y puede iniciar más rápido que un paquete de un solo archivo.
pyinstaller --name MiAplicacion app.py
Entrega toda la carpeta de dist/MiAplicacion, no solamente el EXE.
Crear un solo archivo
pyinstaller --onefile --name MiAplicacion app.py
--onefile produce un ejecutable único. Durante el inicio, el programa necesita preparar sus recursos en una ubicación temporal, por lo que puede tardar más en abrir. Prueba ambos modos antes de elegir.
Preparar el icono
Windows utiliza normalmente archivos .ico. Cambiar únicamente la extensión de un PNG no crea un icono válido. Puedes convertirlo con Pillow:
from PIL import Image
imagen = Image.open("logo.png").convert("RGBA")
imagen.save(
"logo.ico",
sizes=[(16, 16), (32, 32), (48, 48), (256, 256)],
)
Incluye varios tamaños para que el icono se vea correctamente en el explorador, accesos directos y ventanas.
Asignar el icono
pyinstaller --onefile --icon=logo.ico --name MiAplicacion app.py
Si Windows sigue mostrando un icono anterior, puede tratarse de la caché del sistema. Cambia temporalmente el nombre del ejecutable o prueba en otra carpeta antes de concluir que la compilación falló.
Ocultar la consola
Para una aplicación gráfica:
pyinstaller --onefile --windowed --icon=logo.ico app.py
--windowed o --noconsole evita abrir la ventana de terminal. No lo uses mientras depuras, porque perderás mensajes impresos y tracebacks. Primero crea una compilación con consola, corrige los errores y después activa el modo gráfico.
Añadir imágenes y archivos
Una aplicación puede depender de recursos externos:
pyinstaller --onefile --add-data "assets;assets" app.py
En Windows, origen y destino suelen separarse con punto y coma. Consulta la sintaxis de tu versión y sistema.
Resolver rutas dentro del paquete
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
logo = ruta_recurso("assets/logo.png")
En versiones modernas, muchas aplicaciones pueden basarse en __file__, pero el patrón debe probarse en desarrollo y empaquetado. No uses el directorio de trabajo actual como si siempre fuera la carpeta del programa.
El archivo SPEC
PyInstaller crea un archivo .spec que describe análisis, recursos y salida. Para configuraciones complejas, edítalo y construye con:
pyinstaller app.spec
Guarda el SPEC en el control de versiones cuando sea parte del proceso oficial de construcción.
Imports ocultos
Algunas bibliotecas cargan módulos dinámicamente y PyInstaller no los detecta:
pyinstaller --hidden-import=nombre_modulo app.py
No añadas imports ocultos al azar. Ejecuta el EXE desde una consola, lee el error y confirma qué módulo falta. Para paquetes complejos pueden existir hooks oficiales.
Información de versión
En Windows puedes añadir metadatos como nombre del producto, compañía y versión mediante un archivo de recursos y la opción correspondiente. Mantén la versión sincronizada con el código y con el nombre de la distribución.
Guardar datos del usuario
No escribas configuraciones junto al EXE si la aplicación está instalada en una carpeta protegida. Utiliza una ubicación adecuada del perfil del usuario. Separa recursos de solo lectura de datos modificables.
Firmar el ejecutable
Un ejecutable sin firma puede generar advertencias de reputación. La firma de código utiliza un certificado y herramientas de Windows. Firmar no convierte automáticamente el programa en seguro, pero permite verificar al editor y detectar modificaciones posteriores.
Antivirus y falsos positivos
Los ejecutables empaquetados pueden activar análisis adicionales. Evita ofuscar, descargar código inesperadamente o solicitar permisos administrativos sin necesidad. Publica hashes y distribuye desde un sitio confiable. Si existe un falso positivo, utiliza los canales de revisión del proveedor de seguridad.
Crear una construcción reproducible
python -m pip freeze > requirements-build.txt
pyinstaller --clean --noconfirm app.spec
Registra la versión de Python, PyInstaller y dependencias. Construye en un entorno limpio y automatiza el proceso cuando el proyecto crezca.
Probar en otro equipo
No basta con ejecutar el EXE en la máquina de desarrollo. Prueba en una instalación limpia de Windows con permisos normales. Revisa inicio, cierre, archivos, red, actualizaciones, escalado de pantalla y caracteres no ASCII.
Errores frecuentes
Los problemas habituales son convertir un PNG cambiando la extensión, olvidar archivos de datos, activar --windowed demasiado pronto, entregar solo una parte de la carpeta, construir para otro sistema y depender del directorio actual. También es un error asumir que --onefile siempre es la mejor opción.
Conclusión
PyInstaller permite distribuir aplicaciones Python como ejecutables de Windows y asignarles un icono profesional. Construye primero en modo de carpeta y con consola, prepara un ICO real, gestiona rutas correctamente y utiliza un archivo SPEC para proyectos complejos. La distribución solo está completa después de probar el resultado en otro equipo, documentar dependencias y aplicar prácticas de seguridad.





