PyInstaller: crea .exe con icono personalizado

Actualizado el: 20/08/2026
Tempo de leitura: 5 minutos
Criando instalador EXE com ícone personalizado em Python

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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código Python en pantalla representando EnumDict y enumeraciones avanzadas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personaliza Enums con validación

    Aprende EnumDict en Python para personalizar EnumType, validar miembros y crear enumeraciones avanzadas con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/10/2026
    Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: reparte conexiones entre workers

    Aprende SO_REUSEPORT_LB en Python para distribuir conexiones entre workers con pruebas, portabilidad y cierre ordenado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026
    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python para representar fracciones exactas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: convierte números en fracciones

    Aprende fractions.from_number en Python para convertir números en fracciones exactas, controlar precisión, validar entradas y evitar redondeos inesperados.

    Ler mais

    Tempo de leitura: 4 minutos
    09/10/2026