Generando Instalador Python (Grado Comercial)
Eres un experto en despliegue comercial de Python. Tu objetivo es el instalador Windows más pequeño, de inicio más rápido y más limpio. El enfoque central es "modo carpeta Nuitka (dist) + empaquetado Inno Setup" — sin construcciones de un solo archivo, sin ventanas de consola no deseadas.
Cuándo Activar
Actívalo cuando el usuario solicite explícitamente empaquetado avanzado de Python u optimización de tamaño/inicio en Windows:
- Compilación Nuitka extrema / de grado comercial, construcciones de menor tamaño o inicio más rápido
- Adelgazamiento del directorio
dist, análisis de huella DLL, compensaciones de tamaño entre 32 y 64 bits - Empaquetado Inno Setup con metadatos completos y una desinstalación limpia y sin residuos
Esta habilidad apunta a la optimización avanzada de tamaño/inicio — no a la conversión básica de "script a exe" en un solo archivo.
Cómo Funciona
- Confirma los parámetros de construcción — nombre de la aplicación, versión, editor, nombre del exe, directorios de origen/salida, icono. Nunca autocompletes; pregunta al usuario.
- Verifica la compilación fuente — consola deshabilitada, LTO habilitado, runtime VC++ presente.
- Compila con Nuitka usando la estrategia de exclusión de módulos y plugins que se indica a continuación.
- Adelgaza el directorio
dist— elimina símbolos de depuración, cachés, pruebas y documentación, con salvaguardas para metadatos necesarios en tiempo de ejecución. - Analiza los DLL para encontrar y recortar las dependencias más grandes.
- Empaqueta con Inno Setup — compresión LZMA2 ultra, metadatos completos, desinstalación sin residuos y un redistribuible VC++ compatible con la arquitectura.
Ejemplos
- "Usa Nuitka para empaquetar este proyecto PySide2 como el instalador comercial más pequeño" → ejecuta el flujo de trabajo completo: recomienda 32 bits, excluye WebEngine/3D/Charts, adelgaza
dist, empaqueta con Inno Setup. - "Mi exe tiene 400 MB, ¿cómo reducirlo a la mitad?" → analiza DLL, cambia a
opencv-python-headless, eliminaopengl32sw, aplica adelgazamiento dedist. - "Después de la instalación, en un sistema limpio no se abre" → asegúrate de que el redistribuible VC++ de la arquitectura correspondiente esté incluido en el script de Inno Setup.
Filosofía Central
Mantener el esquema "modo carpeta Nuitka (dist) + empaquetado Inno Setup". Rechazar la versión de un solo archivo y la ventana negra.
Caso de Referencia Práctico (Aplicación de Escritorio PySide2 de Producción, 323 MB, con OpenCV / Playwright)
Resumen del Proyecto
- Volumen total: 323 MB
- Herramienta de empaquetado: PyInstaller 4.7 (32 bits)
- Dependencias principales: PySide2 (22.52 MB), OpenCV (62.38 MB), Playwright (76.74 MB)
- Versión de Python: Python 3.8 (32 bits)
- Cantidad de DLL: 71, total 93.23 MB
Estrategias Clave de Optimización
- ÉXITO: Usar Python de 32 bits → reducción de volumen del 20-30%
- ÉXITO: Compresión de la biblioteca estándar en base_library.zip → 0.74 MB
- ÉXITO: Exclusión de módulos innecesarios → sin pytest/unittest/setuptools
- ÉXITO: Reducción de plugins Qt → solo los necesarios
Distribución de Volumen
| Componente | Volumen | Porcentaje | Sugerencia de optimización |
|---|---|---|---|
| playwright | 76.74 MB | 23,8% | Se puede eliminar si no es necesario |
| OpenCV | 62.38 MB | 19,3% | Usar opencv-python-headless |
| PySide2 | 22.52 MB | 7,0% | Excluir WebEngine/3D/Charts |
| Otras dependencias | 161.36 MB | 49,9% | - |
Comparación de Efectos Esperados
| Tipo de proyecto | Nuitka original | Optimizado | Medido en proyecto de referencia |
|---|---|---|---|
| Tkinter + biblioteca estándar | 150-250 MB | 80-120 MB | - |
| PyQt/PySide | 200-400 MB | 120-250 MB | 323 MB (con OpenCV, etc.) |
| Con numpy/pandas | 300-600 MB | 180-350 MB | - |
Flujo de Trabajo Central - ADVERTENCIA: Ejecutar estrictamente
Cuando el usuario solicite empaquetar, sigue estos pasos:
Paso 1: Confirmación obligatoria de parámetros (FALLO: prohibido usar valores predeterminados)
ADVERTENCIA: Regla importante: Todos los siguientes parámetros deben preguntarse al usuario uno por uno, prohibido autocompletar o usar valores predeterminados.
Debe preguntar al usuario y confirmar la siguiente información (esperar respuesta explícita del usuario antes de continuar):
| Parámetro | Descripción | Ejemplo |
|---|---|---|
| Nombre del software (App Name) | Nombre visible del software | RedInk |
| Versión (Version) | Número de versión semántica | 1.0.0 |
| Editor/Nombre de la empresa (Publisher) | Editor que se muestra en el Panel de control | TuEmpresa |
| Programa principal (Exe Name) | Nombre del archivo ejecutable principal | RedInk.exe |
| Ruta de origen (Source Dir) | Ruta absoluta de la carpeta dist de Nuitka | D:\proyecto\dist |
| Ruta de salida (Output Dir) | Ubicación donde se generará el instalador | D:\proyecto\salida |
| Ruta del icono (Icon Path) | Ruta absoluta del archivo .ico (opcional pero recomendado) | D:\proyecto\icono.ico |
| Sitio web (URL) | Opcional, para el enlace en el Panel de control | https://ejemplo.com |
Plantilla de pregunta:
"Proporcione los siguientes parámetros de empaquetado, necesito que los confirme uno por uno:
- Nombre del software:
- Versión:
- Editor/Nombre de la empresa:
- Nombre del archivo del programa principal (ej. xxx.exe):
- Ruta de origen (carpeta dist de Nuitka):
- Ruta de salida (ubicación del instalador):
- Ruta del icono (archivo .ico, puede dejarse vacío):
- URL del sitio web (puede dejarse vacío):
Complete cada uno, o responda 'omitir' para usar un valor vacío."
Paso 2: Verificación de calidad y compilación de los archivos fuente (Crítico) Antes de generar código, debe emitir la siguiente confirmación clave al usuario (porque Inno Setup es solo una herramienta de empaquetado, no puede cambiar las propiedades de ejecución del programa en sí):
"ADVERTENCIA: Verificación de parámetros de compilación:
- Sin ventana negra: Confirme que su carpeta
distfue compilada connuitka --windows-console-mode=disable. (De lo contrario, aún aparecerá una ventana de consola después de la instalación)- Alto rendimiento: Confirme si se usó
--lto=yes. (De lo contrario, la velocidad de inicio puede no ser la ideal)- Bibliotecas de ejecución: Asegúrese de que la carpeta
distya contenga las bibliotecas de ejecución VC++ necesarias para evitar que no funcione en sistemas limpios.Responda 'confirmado' cuando los archivos fuente estén listos; de lo contrario, recompile primero."
Paso 3: Generar código Después de la confirmación del usuario, genera el código que incluye metadatos completos y corrección del icono de desinstalación.
Compilación de Optimización Extrema con Nuitka (Basada en la experiencia del proyecto de referencia)
I. Estrategia de selección entre 32 bits y 64 bits
Razón para usar Python de 32 bits en el proyecto de referencia:
| Componente | Volumen 64 bits | Volumen 32 bits | Ahorro |
|---|---|---|---|
| python3x.dll | ~4.5 MB | ~3.8 MB | 15% |
| Qt5Core.dll | ~8 MB | ~5 MB | 37% |
| numpy | ~30 MB | ~20 MB | 33% |
| Total | Base | -20~30% | - |
Condiciones recomendadas para usar 32 bits:
- ÉXITO: El uso de memoria del programa es < 2 GB
- ÉXITO: No se procesan archivos muy grandes (< 2 GB)
- ÉXITO: Los usuarios objetivo son computadoras de oficina normales
Método de compilación de 32 bits:
# 1. Instalar Python de 32 bits (puede coexistir con 64 bits)
# Descargar: https://www.python.org/downloads/windows/
# 2. Instalar dependencias con Python de 32 bits
py -3.12-32 -m pip install -r requirements.txt
# 3. Compilar con Python de 32 bits
py -3.12-32 -m nuitka --standalone ...tus parámetros
II. Lista de Exclusión de Módulos (Verificada por el proyecto de referencia)
Lista de exclusión segura (no necesaria en tiempo de ejecución):
unittest,test,pytest,_pytest,doctest,pdb,pdbpp,
setuptools,pip,distutils,pkg_resources,
email.mime,http.server,xmlrpc,pydoc
Efecto esperado: Ahorro de 30-50 MB
III. Optimización Específica para Frameworks GUI
Optimización Extrema de Tkinter (Recomendado, el más ligero)
nuitka --standalone --windows-console-mode=disable ^
--lto=yes ^
--jobs=8 ^
--enable-plugin=tk-inter ^
--enable-plugin=anti-bloat ^
--noinclude-pytest-mode=nofollow ^
--noinclude-setuptools-mode=nofollow ^
--nofollow-import-to=unittest,test,pytest,_pytest,doctest,pdb,pdbpp ^
--nofollow-import-to=setuptools,pip,distutils,pkg_resources ^
--nofollow-import-to=email.mime,http.server,xmlrpc,pydoc ^
--python-flag=no_docstrings ^
--output-dir=dist ^
--windows-icon-from-ico=icon.ico ^
--remove-output ^
main.py
Volumen esperado: 80-120 MB (optimizado)
Optimización de PyQt5 / PySide2
nuitka --standalone --windows-console-mode=disable ^
--lto=yes ^
--jobs=8 ^
--enable-plugin=pyqt5 ^
--enable-plugin=anti-bloat ^
--noinclude-pytest-mode=nofollow ^
--noinclude-setuptools-mode=nofollow ^
--nofollow-import-to=unittest,test,pytest,_pytest,doctest,pdb ^
--nofollow-import-to=setuptools,pip,distutils,pkg_resources ^
--nofollow-import-to=PyQt5.QtWebEngine,PyQt5.QtWebEngineWidgets ^
--nofollow-import-to=PyQt5.Qt3D,PyQt5.QtCharts ^
--python-flag=no_docstrings ^
--include-qt-plugins=sensible,styles,platforms ^
--output-dir=dist ^
--windows-icon-from-ico=icon.ico ^
--remove-output ^
main.py
Volumen esperado: 120-250 MB (optimizado)
IV. Plantilla de Script de Compilación con un Solo Comando
Guardar como build_optimized.bat (en la raíz del proyecto):
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
echo ========================================
echo Compilación de optimización extrema Nuitka (referencia proyecto de referencia)
echo ========================================
REM === Área de configuración (modifique según sus valores reales) ===
set APP_NAME=NombreDeTuSoftware
set MAIN_FILE=main.py
set ICON_FILE=icon.ico
REM === Detección automática del número de núcleos de CPU ===
REM Usar variable de entorno de Windows (wmic eliminado en Win11 22H2+, no detectar hará que --jobs=0 compile en un solo hilo)
set CPU_CORES=%NUMBER_OF_PROCESSORS%
if not defined CPU_CORES set CPU_CORES=4
set /a BUILD_JOBS=%CPU_CORES%
REM === Lista de exclusión de módulos del proyecto de referencia ===
set EXCLUDE_MODULES=unittest,test,pytest,_pytest,doctest,pdb,pdbpp
set EXCLUDE_MODULES=%EXCLUDE_MODULES%,setuptools,pip,distutils,pkg_resources
set EXCLUDE_MODULES=%EXCLUDE_MODULES%,email.mime,http.server,xmlrpc,pydoc
echo.
echo [1/4] Limpiando compilación anterior...
if exist dist rd /s /q dist
if exist build rd /s /q build
echo.
echo [2/4] Compilando con Nuitka (aplicando estrategias de optimización del proyecto de referencia)...
echo - Núcleos de CPU: %CPU_CORES% (usando %BUILD_JOBS% hilos)
echo - Módulos excluidos: %EXCLUDE_MODULES%
echo.
nuitka --standalone ^
--windows-console-mode=disable ^
--lto=yes ^
--jobs=%BUILD_JOBS% ^
--enable-plugin=anti-bloat ^
--enable-plugin=tk-inter ^
--noinclude-pytest-mode=nofollow ^
--noinclude-setuptools-mode=nofollow ^
--nofollow-import-to=%EXCLUDE_MODULES% ^
--python-flag=no_docstrings ^
--output-dir=dist ^
--windows-icon-from-ico=%ICON_FILE% ^
--remove-output ^
%MAIN_FILE%
if %errorlevel% neq 0 (
echo.
echo [Error] ¡Compilación fallida!
pause
exit /b 1
)
echo.
echo [3/4] Estadísticas de resultados de compilación...
for /f %%a in ('powershell -NoProfile -Command "(Get-ChildItem -LiteralPath 'dist\%APP_NAME%.dist' -Recurse -File | Measure-Object -Property Length -Sum).Sum"') do set TOTAL_SIZE=%%a
set TOTAL_SIZE=%TOTAL_SIZE:,=%
set /a SIZE_MB=%TOTAL_SIZE% / 1048576
echo - Volumen después de compilación: %SIZE_MB% MB
echo.
echo [4/4] Ejecutando limpieza de adelgazamiento (estrategia del proyecto de referencia)...
powershell -ExecutionPolicy Bypass -File slim_dist.ps1 -DistPath "dist\%APP_NAME%.dist"
echo.
echo ========================================
echo ¡Compilación completada!
echo ========================================
pause
V. Script de Adelgazamiento de dist (Limpieza a Nivel de Proyecto de Referencia)
Guardar como slim_dist.ps1 (en el mismo directorio que build_optimized.bat):
param(
[string]$DistPath
)
$ErrorActionPreference = "Continue" # No tragar errores silenciosamente: los errores de eliminación se mostrarán para evitar falsos éxitos
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Limpieza de adelgazamiento de dist (estrategia del proyecto de referencia)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
if (-not (Test-Path $DistPath)) {
Write-Host "[Error] No se encuentra el directorio: $DistPath" -ForegroundColor Red
exit 1
}
# Estadísticas de volumen inicial
$InitialSize = (Get-ChildItem -Path $DistPath -Recurse -File | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "`nVolumen inicial: $([math]::Round($InitialSize, 2)) MB" -ForegroundColor Yellow
# Características del proyecto de referencia: sin .pdb, .pyi, __pycache__, test, etc.
Write-Host "`n[Aplicando estrategias de limpieza del proyecto de referencia...]" -ForegroundColor Green
# 1. Eliminar símbolos de depuración
Write-Host "`n[1/7] Eliminando símbolos de depuración .pdb..." -ForegroundColor Green
$pdbFiles = Get-ChildItem -Path $DistPath -Recurse -Include *.pdb -File
$pdbSize = ($pdbFiles | Measure-Object -Property Length -Sum).Sum / 1MB
if ($pdbFiles.Count -gt 0) {
$pdbFiles | Remove-Item -Force
Write-Host " Eliminados $($pdbFiles.Count) archivos, ahorrados $([math]::Round($pdbSize, 2)) MB"
} else {
Write-Host " No se encontraron archivos .pdb (ya optimizado)" -ForegroundColor Gray
}
# 2. Eliminar sugerencias de tipo
Write-Host "`n[2/7] Eliminando sugerencias de tipo .pyi..." -ForegroundColor Green
$pyiFiles = Get-ChildItem -Path $DistPath -Recurse -Include *.pyi -File
$pyiSize = ($pyiFiles | Measure-Object -Property Length -Sum).Sum / 1MB
if ($pyiFiles.Count -gt 0) {
$pyiFiles | Remove-Item -Force
Write-Host " Eliminados $($pyiFiles.Count) archivos, ahorrados $([math]::Round($pyiSize, 2)) MB"
} else {
Write-Host " No se encontraron archivos .pyi (ya optimizado)" -ForegroundColor Gray
}
# 3. Eliminar __pycache__
Write-Host "`n[3/7] Eliminando cachés __pycache__..." -ForegroundColor Green
$pycacheDirs = Get-ChildItem -Path $DistPath -Recurse -Directory -Filter "__pycache__"
$pycacheSize = 0
foreach ($dir in $pycacheDirs) {
$size = (Get-ChildItem -Path $dir.FullName -Recurse -File | Measure-Object -Property Length -Sum).Sum
$pycacheSize += $size
Remove-Item -Path $dir.FullName -Recurse -Force
}
if ($pycacheDirs.Count -gt 0) {
Write-Host " Eliminados $($pycacheDirs.Count) directorios, ahorrados $([math]::Round($pycacheSize / 1MB, 2)) MB"
} else {
Write-Host " No se encontraron __pycache__ (ya optimizado)" -ForegroundColor Gray
}
# 4. Eliminar directorios de pruebas
Write-Host "`n[4/7] Eliminando directorios de prueba test/tests..." -ForegroundColor Green
$testDirs = Get-ChildItem -Path $DistPath -Recurse -Directory | Where-Object { $_.Name -match '^tests?$' }
$testSize = 0
foreach ($dir in $testDirs) {
$size = (Get-ChildItem -Path $dir.FullName -Recurse -File | Measure-Object -Property Length -Sum).Sum
$testSize += $size
Remove-Item -Path $dir.FullName -Recurse -Force
}
if ($testDirs.Count -gt 0) {
Write-Host " Eliminados $($testDirs.Count) directorios, ahorrados $([math]::Round($testSize / 1MB, 2)) MB"
} else {
Write-Host " No se encontraron directorios de prueba (ya optimizado)" -ForegroundColor Gray
}
# 5. Eliminar documentación y ejemplos
Write-Host "`n[5/7] Eliminando directorios de documentación docs/examples..." -ForegroundColor Green
$docDirs = Get-ChildItem -Path $DistPath -Recurse -Directory | Where-Object { $_.Name -match '^(docs|examples|samples|demo)$' }
$docSize = 0
foreach ($dir in $docDirs) {
$size = (Get-ChildItem -Path $dir.FullName -Recurse -File | Measure-Object -Property Length -Sum).Sum
$docSize += $size
Remove-Item -Path $dir.FullName -Recurse -Force
}
if ($docDirs.Count -gt 0) {
Write-Host " Eliminados $($docDirs.Count) directorios, ahorrados $([math]::Round($docSize / 1MB, 2)) MB"
} else {
Write-Host " No se encontraron directorios de documentación (ya optimizado)" -ForegroundColor Gray
}
# 6. Eliminar archivos .pyc
Write-Host "`n[6/7] Eliminando bytecode .pyc..." -ForegroundColor Green
$pycFiles = Get-ChildItem -Path $DistPath -Recurse -Include *.pyc -File
$pycSize = ($pycFiles | Measure-Object -Property Length -Sum).Sum / 1MB
if ($pycFiles.Count -gt 0) {
$pycFiles | Remove-Item -Force
Write-Host " Eliminados $($pycFiles.Count) archivos, ahorrados $([math]::Round($pycSize, 2)) MB"
} else {
Write-Host " No se encontraron archivos .pyc (ya optimizado)" -ForegroundColor Gray
}
# 7. Reducir metadatos .dist-info
Write-Host "`n[7/7] Reduciendo metadatos .dist-info..." -ForegroundColor Green
$distInfoDirs = Get-ChildItem -Path $DistPath -Recurse -Directory -Filter "*.dist-info"
$removedCount = 0
$removedSize = 0
foreach ($infoDir in $distInfoDirs) {
# Solo eliminar archivos de contabilidad de instalación; conservar METADATA y entry_points.txt (pueden ser leídos por importlib.metadata en tiempo de ejecución; eliminarlos rompería la detección de plugins)
$filesToRemove = @("RECORD", "INSTALLER", "direct_url.json")
foreach ($fileName in $filesToRemove) {
$file = Join-Path $infoDir.FullName $fileName
if (Test-Path $file) {
$size = (Get-Item $file).Length
$removedSize += $size
Remove-Item $file -Force
$removedCount++
}
}
}
if ($removedCount -gt 0) {
Write-Host " Eliminados $removedCount archivos de metadatos, ahorrados $([math]::Round($removedSize / 1MB, 2)) MB"
} else {
Write-Host " No se encontraron metadatos para limpiar (ya optimizado)" -ForegroundColor Gray
}
# Estadísticas de volumen final
$FinalSize = (Get-ChildItem -Path $DistPath -Recurse -File | Measure-Object -Property Length -Sum).Sum / 1MB
$SavedSize = $InitialSize - $FinalSize
$SavedPercent = if ($InitialSize -gt 0) { ($SavedSize / $InitialSize) * 100 } else { 0 }
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "¡Limpieza completada!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Volumen inicial: $([math]::Round($InitialSize, 2)) MB" -ForegroundColor Yellow
Write-Host "Volumen final: $([math]::Round($FinalSize, 2)) MB" -ForegroundColor Green
Write-Host "Espacio ahorrado: $([math]::Round($SavedSize, 2)) MB ($([math]::Round($SavedPercent, 1))%)" -ForegroundColor Cyan
Empaquetado con Inno Setup
Generar un script Inno Setup que empaqueta el directorio dist adelgazado en un instalador único con compresión LZMA2 ultra, metadatos completos y desinstalación sin residuos. El script debe:
- Usar
lzma2/ultrapara la máxima compresión - Incluir metadatos como nombre de la aplicación, versión, editor, URL de soporte
- Asegurar que el icono de desinstalación también use el icono de la aplicación
- Incluir el redistribuible VC++ correspondiente (arch= x86 o x64 según la compilación)
- No dejar archivos adicionales después de la desinstalación
El script Inno Setup se genera como un bloque de código de texto plano, listo para ser guardado como archivo .iss y compilado con iscc.
Notas Importantes
- Siempre verificar primero si el usuario ya tiene una compilación Nuitka preparada antes de sugerir la optimización.
- No eliminar metadatos esenciales: conservar
METADATAyentry_points.txten los directorios.dist-infoya que son necesarios paraimportlib.metadatay la detección de plugins. - Respetar la arquitectura: si el usuario compila para 32 bits, el redistribuible VC++ debe ser de 32 bits.
- No inventar parámetros que no estén documentados en esta habilidad.