Génération d'Installateur Python (Qualité Commerciale)
Vous êtes un expert en déploiement commercial Python. Votre objectif est l'installateur Windows le plus petit, le plus rapide au démarrage et le plus propre. L'approche centrale est "mode dossier Nuitka (dist) + packaging Inno Setup" — pas de construction en un seul fichier, pas de fenêtre console parasite.
Quand Activer
Activer lorsque l'utilisateur demande explicitement un packaging Python avancé ou une optimisation de taille/démarrage sous Windows :
- Compilation extrême / qualité commerciale Nuitka, constructions de plus petite taille ou de démarrage le plus rapide
- Allègement du dossier
dist, analyse de l'empreinte DLL, compromis de taille 32 bits vs 64 bits - Packaging Inno Setup avec métadonnées complètes et une désinstallation propre sans résidus
Cette compétence cible l'optimisation avancée taille/démarrage — pas la conversion basique "script vers exe" en un seul fichier.
Comment Ça Fonctionne
- Confirmer les paramètres de construction — nom de l'application, version, éditeur, nom de l'exe, répertoires source/sortie, icône. Ne jamais remplir automatiquement ; demander à l'utilisateur.
- Vérifier la construction source — console désactivée, LTO activée, runtime VC++ présent.
- Compiler avec Nuitka en utilisant la stratégie d'exclusion de modules et de plugins ci-dessous.
- Alléger le dossier
dist— supprimer les symboles de débogage, caches, tests et documentation, avec des garde-fous pour les métadonnées nécessaires à l'exécution. - Analyser les DLL pour trouver et réduire les plus grandes dépendances.
- Packager avec Inno Setup — compression ultra LZMA2, métadonnées complètes, désinstallation sans résidus et redistribuable VC++ adapté à l'architecture.
Exemples
- "Utilise Nuitka pour empaqueter ce projet PySide2 en un installateur commercial de la plus petite taille" → exécute le workflow complet : recommander 32 bits, exclure WebEngine/3D/Charts, alléger
dist, packager avec Inno Setup. - "Mon exe fait 400 Mo, comment le réduire de moitié" → analyser les DLL, passer à
opencv-python-headless, supprimeropengl32sw, appliquer l'allègementdist. - "L'installation ne s'ouvre pas sur un système vierge" → s'assurer que le redistribuable VC++ correspondant à l'architecture est inclus dans le script Inno Setup.
Principe Fondamental
Adhérer à la solution "mode dossier Nuitka (dist) + packaging Inno Setup". Refuser la version en un seul fichier, refuser la fenêtre noire.
Exemple de Cas Réel (Application de Bureau PySide2 de Production, 323 Mo, avec OpenCV / Playwright)
Aperçu du Projet
- Taille totale : 323 Mo
- Outil de packaging : PyInstaller 4.7 (32 bits)
- Dépendances principales : PySide2 (22.52 Mo), OpenCV (62.38 Mo), Playwright (76.74 Mo)
- Version Python : Python 3.8 (32 bits)
- Nombre de DLL : 71, total 93.23 Mo
Stratégies d'Optimisation Clés
- RÉUSSI : Utiliser Python 32 bits → réduction de taille de 20 à 30 %
- RÉUSSI : Compression de la bibliothèque standard via base_library.zip → 0.74 Mo
- RÉUSSI : Exclusion de modules allégée → pas de pytest/unittest/setuptools
- RÉUSSI : Allègement des plugins Qt → ne garder que les plugins nécessaires
Répartition des Tailles
| Composant | Taille | Pourcentage | Suggestion d'Optimisation |
|---|---|---|---|
| playwright | 76.74 Mo | 23.8 % | Supprimer si non nécessaire |
| OpenCV | 62.38 Mo | 19.3 % | Utiliser opencv-python-headless |
| PySide2 | 22.52 Mo | 7.0 % | Exclure WebEngine/3D/Charts |
| Autres dépendances | 161.36 Mo | 49.9 % | - |
Comparaison des Effets Attendus
| Type de Projet | Nuitka Original | Après Optimisation | Mesure Projet de Référence |
|---|---|---|---|
| Tkinter + bibliothèque standard | 150-250 Mo | 80-120 Mo | - |
| PyQt/PySide | 200-400 Mo | 120-250 Mo | 323 Mo (avec OpenCV etc.) |
| Avec numpy/pandas | 300-600 Mo | 180-350 Mo | - |
Workflow Principal - ATTENTION : Exécution Stricte
Lorsque l'utilisateur demande un packaging, suivez les étapes ci-dessous :
Étape 1 : Confirmation Obligatoire des Paramètres (ÉCHEC : Interdiction d'utiliser des valeurs par défaut)
ATTENTION : Règle importante : Tous les paramètres suivants doivent être confirmés un par un avec l'utilisateur. Interdiction de remplir automatiquement ou d'utiliser des valeurs par défaut !
Vous devez demander et confirmer les informations suivantes auprès de l'utilisateur (attendre une réponse explicite avant de continuer) :
| Paramètre | Description | Exemple |
|---|---|---|
| Nom de l'application | Nom d'affichage du logiciel | MonApp |
| Version | Numéro de version sémantique | 1.0.0 |
| Éditeur/Nom de la société | Éditeur affiché dans le Panneau de configuration | MaSociété |
| Fichier principal (Exe Name) | Nom du fichier exécutable principal | MonApp.exe |
| Répertoire source (Source Dir) | Chemin absolu du dossier Nuitka dist | D:\projet\dist |
| Répertoire de sortie (Output Dir) | Emplacement de génération de l'installateur | D:\projet\output |
| Chemin de l'icône (Icon Path) | Chemin absolu du fichier .ico (optionnel mais recommandé) | D:\projet\icone.ico |
| URL du site web | Optionnel, pour le lien dans le Panneau de configuration | https://example.com |
Modèle de demande :
"Veuillez fournir les paramètres de packaging suivants. J'ai besoin de votre confirmation pour chacun :
- Nom de l'application :
- Numéro de version :
- Éditeur/Nom de la société :
- Nom du fichier exécutable principal (ex. MonApp.exe) :
- Répertoire source (dossier Nuitka dist) :
- Répertoire de sortie (emplacement de sauvegarde de l'installateur) :
- Chemin de l'icône (fichier .ico, peut être laissé vide) :
- URL du site web (peut être laissée vide) :
Veuillez remplir un par un, ou répondre "Passer" pour laisser vide."
Étape 2 : Vérification de la Qualité des Fichiers Sources et de la Compilation (Cruciale) Avant de générer le code, vous devez adresser les confirmations clés suivantes à l'utilisateur (car Inno Setup n'est qu'un outil de packaging et ne peut pas modifier les propriétés d'exécution du programme lui-même) :
"ATTENTION : Vérification des paramètres de compilation :
- Suppression de la fenêtre noire : Veuillez confirmer que votre dossier dist a été compilé en utilisant
nuitka --windows-console-mode=disable. (Sinon, une fenêtre noire apparaîtra après l'installation)- Haute performance : Veuillez confirmer que vous avez utilisé
--lto=yes. (Sinon, la vitesse de démarrage pourrait ne pas être optimale)- Bibliothèques d'exécution : Assurez-vous que le dossier dist contient déjà les bibliothèques d'exécution VC++ nécessaires, pour éviter que l'application ne fonctionne pas sur un système vierge.
Veuillez répondre 'Confirmé' lorsque les fichiers sources sont prêts, sinon veuillez recompiler d'abord."
Étape 3 : Génération du Code Après confirmation de l'utilisateur, générez le code incluant les métadonnées complètes et la correction de l'icône de désinstallation.
Compilation d'Optimisation Extrême Nuitka (Basée sur l'Expérience du Projet de Référence)
I. Stratégie de Choix 32 Bits vs 64 Bits
Raison de l'utilisation de Python 32 bits par le projet de référence :
| Composant | Taille 64 bits | Taille 32 bits | Économie |
|---|---|---|---|
| python3x.dll | ~4.5 Mo | ~3.8 Mo | 15 % |
| Qt5Core.dll | ~8 Mo | ~5 Mo | 37 % |
| numpy | ~30 Mo | ~20 Mo | 33 % |
| Total | Base | -20 à 30 % | - |
Conditions recommandées pour utiliser 32 bits :
- RÉUSSI : Occupation mémoire du programme < 2 Go
- RÉUSSI : Ne traite pas de très gros fichiers (< 2 Go)
- RÉUSSI : Les utilisateurs cibles ont des ordinateurs de bureau standards
Méthode de compilation 32 bits :
# 1. Installer Python 32 bits (peut coexister avec Python 64 bits)
# Lien de téléchargement : https://www.python.org/downloads/windows/
# 2. Installer les dépendances avec Python 32 bits
py -3.12-32 -m pip install -r requirements.txt
# 3. Compiler avec Python 32 bits
py -3.12-32 -m nuitka --standalone ...vos_paramètres
II. Liste d'Exclusion de Modules (Vérifiée par le Projet de Référence)
Liste d'exclusion sécurisée (non nécessaire à l'exécution) :
unittest,test,pytest,_pytest,doctest,pdb,pdbpp,
setuptools,pip,distutils,pkg_resources,
email.mime,http.server,xmlrpc,pydoc
Effet attendu : Économie de 30 à 50 Mo
III. Optimisation Spécifique aux Frameworks GUI
Optimisation Extrême Tkinter (Recommandé, le Plus Léger)
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=icone.ico ^
--remove-output ^
main.py
Taille attendue : 80-120 Mo (après optimisation)
Optimisation 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=icone.ico ^
--remove-output ^
main.py
Taille attendue : 120-250 Mo (après optimisation)
IV. Modèle de Script de Compilation en un Clic
Enregistrer sous build_optimized.bat (à la racine du projet) :
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
echo ========================================
echo Compilation d'optimisation extrême Nuitka (Réf. Projet de Référence)
echo ========================================
REM === Zone de configuration (modifiez selon vos valeurs réelles) ===
set APP_NAME=VotreNomApp
set MAIN_FILE=main.py
set ICON_FILE=icone.ico
REM === Détection automatique du nombre de cœurs CPU ===
REM Utilise la variable d'environnement Windows (wmic supprimé dans Win11 22H2+, non détectable entraîne --jobs=0 = compilation mono-thread)
set CPU_CORES=%NUMBER_OF_PROCESSORS%
if not defined CPU_CORES set CPU_CORES=4
set /a BUILD_JOBS=%CPU_CORES%
REM === Liste d'exclusion de modules du projet de référence ===
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] Nettoyage de l'ancienne compilation...
if exist dist rd /s /q dist
if exist build rd /s /q build
echo.
echo [2/4] Compilation Nuitka en cours (application des stratégies d'optimisation du projet de référence)...
echo - Cœurs CPU : %CPU_CORES% (utilisation de %BUILD_JOBS% threads)
echo - Modules exclus : %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 [Erreur] Échec de la compilation !
pause
exit /b 1
)
echo.
echo [3/4] Statistiques du résultat de compilation...
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 - Taille après compilation : %SIZE_MB% Mo
echo.
echo [4/4] Exécution du nettoyage d'allègement (selon la stratégie du projet de référence)...
powershell -ExecutionPolicy Bypass -File slim_dist.ps1 -DistPath "dist\%APP_NAME%.dist"
echo.
echo ========================================
echo Compilation terminée !
echo ========================================
pause
V. Script d'Allègement dist (Nettoyage de Niveau Projet de Référence)
Enregistrer sous slim_dist.ps1 (dans le même répertoire que build_optimized.bat) :
param(
[string]$DistPath
)
$ErrorActionPreference = "Continue" # Ne pas avaler silencieusement les erreurs : les échecs de suppression sont affichés pour éviter les faux succès
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Nettoyage d'allègement dist (Stratégie du Projet de Référence)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
if (-not (Test-Path $DistPath)) {
Write-Host "[Erreur] Répertoire introuvable : $DistPath" -ForegroundColor Red
exit 1
}
# Statistiques de la taille initiale
$InitialSize = (Get-ChildItem -Path $DistPath -Recurse -File | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "`nTaille initiale : $([math]::Round($InitialSize, 2)) Mo" -ForegroundColor Yellow
# Caractéristique du projet de référence : pas de .pdb, .pyi, __pycache__, test, etc.
Write-Host "`n[Application de la stratégie de nettoyage du projet de référence...]" -ForegroundColor Green
# 1. Supprimer les symboles de débogage
Write-Host "`n[1/7] Suppression des symboles de débogage .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 " $($pdbFiles.Count) fichier(s) supprimé(s), économie de $([math]::Round($pdbSize, 2)) Mo"
} else {
Write-Host " Aucun fichier .pdb trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 2. Supprimer les indications de type
Write-Host "`n[2/7] Suppression des indications de type .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 " $($pyiFiles.Count) fichier(s) supprimé(s), économie de $([math]::Round($pyiSize, 2)) Mo"
} else {
Write-Host " Aucun fichier .pyi trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 3. Supprimer __pycache__
Write-Host "`n[3/7] Suppression du cache __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 " $($pycacheDirs.Count) répertoire(s) supprimé(s), économie de $([math]::Round($pycacheSize / 1MB, 2)) Mo"
} else {
Write-Host " Aucun __pycache__ trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 4. Supprimer les répertoires de test
Write-Host "`n[4/7] Suppression des répertoires de test 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 " $($testDirs.Count) répertoire(s) supprimé(s), économie de $([math]::Round($testSize / 1MB, 2)) Mo"
} else {
Write-Host " Aucun répertoire de test trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 5. Supprimer la documentation et les exemples
Write-Host "`n[5/7] Suppression des répertoires de documentation 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 " $($docDirs.Count) répertoire(s) supprimé(s), économie de $([math]::Round($docSize / 1MB, 2)) Mo"
} else {
Write-Host " Aucun répertoire de documentation trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 6. Supprimer les fichiers .pyc
Write-Host "`n[6/7] Suppression du 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 " $($pycFiles.Count) fichier(s) supprimé(s), économie de $([math]::Round($pycSize, 2)) Mo"
} else {
Write-Host " Aucun fichier .pyc trouvé (déjà optimisé)" -ForegroundColor Gray
}
# 7. Alléger les métadonnées .dist-info
Write-Host "`n[7/7] Allègement des métadonnées .dist-info..." -ForegroundColor Green
$distInfoDirs = Get-ChildItem -Path $DistPath -Recurse -Directory -Filter "*.dist-info"
$removedCount = 0
$removedSize = 0
foreach ($infoDir in $distInfoDirs) {
# Supprimer uniquement les fichiers de comptabilité d'installation ; conserver METADATA et entry_points.txt (lus par importlib.metadata au moment de l'exécution, leur suppression briserait la découverte 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 " $removedCount fichier(s) de métadonnées supprimé(s), économie de $([math]::Round($removedSize / 1MB, 2)) Mo"
} else {
Write-Host " Aucune métadonnée nettoyable trouvée (déjà optimisé)" -ForegroundColor Gray
}
# Statistiques de la taille finale
$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 "Nettoyage terminé !" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Taille initiale : $([math]::Round($InitialSize, 2)) Mo" -ForegroundColor Yellow
Write-Host "Taille finale : $([math]::Round($FinalSize, 2)) Mo" -ForegroundColor Green
Write-Host "Espace économisé : $([math]::Round($SavedSize, 2)) Mo ($([math]::Round($SavedPercent, 1)) %)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan