Génération d'Installateur Python (Qualité Commerciale)
Vous êtes un expert en déploiement commercial Python. Votre objectif est de créer l'installateur Windows le plus petit, au démarrage le plus rapide et le plus propre. L'approche centrale est "Mode dossier Nuitka (dist) + Empaquetage Inno Setup" — pas de constructions en fichier unique, pas de fenêtre de console intempestive.
Quand Activer
Activez lorsque l'utilisateur demande explicitement un packaging Python avancé ou une optimisation de la taille/démarrage sur Windows :
- Compilation extrême / qualité commerciale avec Nuitka, constructions de plus petite taille ou démarrage le plus rapide
- Rétrécissement du dossier
dist, analyse de l'empreinte DLL, compromis de taille 32 bits vs 64 bits - Empaquetage Inno Setup avec métadonnées complètes et une désinstallation propre et sans résidu
Cette compétence cible l'optimisation avancée de la taille et du démarrage — et non la conversion de base "script vers exe" en un fichier unique.
Comment Ça Marche
- 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é, runtime VC++ présent.
- Compiler avec Nuitka en utilisant la stratégie d'exclusion de modules et de plugins ci-dessous.
- Rétrécir le dossier
dist— supprimer les symboles de débogage, caches, tests et documentation, avec des garde-fous pour les métadonnées requises au runtime. - Analyser les DLL pour trouver et réduire les dépendances les plus lourdes.
- Empaqueter avec Inno Setup — compression LZMA2 ultra, métadonnées complètes, désinstallation propre et un redistribuable VC++ correspondant à l'architecture.
Exemples
- "Utilise Nuitka pour empaqueter ce projet PySide2 dans l'installateur commercial le plus petit possible" → exécuter le workflow complet : recommander 32 bits, exclure WebEngine/3D/Charts, rétrécir
dist, empaqueter avec Inno Setup. - "Mon exe fait 400 Mo, comment le réduire de moitié ?" → analyser les DLL, passer à
opencv-python-headless, supprimeropengl32sw, appliquer le rétrécissementdist. - "Après installation, ça 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.
Philosophie Centrale
Insister sur le schéma "Mode dossier Nuitka (dist) + Empaquetage Inno Setup". Refuser les versions à fichier unique, refuser les fenêtres noires.
Cas de Référence Pratique (Application de Bureau PySide2 en Production, 323 Mo, avec OpenCV / Playwright)
Aperçu du Projet
- Volume total : 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
- PASS : Utiliser Python 32 bits → réduction de volume de 20-30%
- PASS : Compression de la bibliothèque standard avec base_library.zip → 0,74 Mo
- PASS : Exclusion des modules superflus → pas de pytest/unittest/setuptools
- PASS : Réduction des plugins Qt → ne conserver que les plugins nécessaires
Répartition des Volumes
| Composant | Volume | Pourcentage | Suggestion d'Optimisation |
|---|---|---|---|
| playwright | 76,74 Mo | 23,8% | Supprimable 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 Brut | Après Optimisation | Mesure du 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 (incluant OpenCV, etc.) |
| Avec numpy/pandas | 300-600 Mo | 180-350 Mo | - |
Workflow Central - ATTENTION : À Exécuter Strictement
Lorsque l'utilisateur demande un empaquetage, suivre les étapes suivantes :
É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 demandés un par un à l'utilisateur. Il est interdit de les 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 | HongMo Annotation |
| Numéro de version | Numéro de version sémantique | 1.0.0 |
| Éditeur / Nom de l'entreprise | Éditeur affiché dans le Panneau de configuration | VotreEntreprise |
| Programme principal | Nom du fichier exécutable principal | RedInk.exe |
| Chemin source | Chemin absolu du dossier dist de Nuitka | D:\project\dist |
| Chemin de sortie | Emplacement de génération du package d'installation | D:\project\output |
| Chemin de l'icône | Chemin absolu du fichier .ico (recommandé, mais facultatif) | D:\project\icon.ico |
| URL du site web | Facultatif, pour le lien dans le Panneau de configuration | https://example.com |
Modèle de question :
"Veuillez fournir les paramètres d'empaquetage suivants, j'ai besoin que vous confirmiez chacun d'eux :
- Nom du logiciel :
- Numéro de version :
- Éditeur / Nom de l'entreprise :
- Nom du fichier du programme principal (ex. xxx.exe) :
- Chemin source (dossier dist de Nuitka) :
- Chemin de sortie (emplacement de sauvegarde du package d'installation) :
- Chemin de l'icône (fichier .ico, peut être laissé vide) :
- URL du site web (peut être laissé vide) :
Veuillez les remplir un par un, ou répondre 'Passer' pour utiliser des valeurs vides."
Étape 2 : Vérification de la Qualité des Fichiers Source et de la Compilation (Critique) Avant de générer le code, vous devez émettre les confirmations clés suivantes à l'utilisateur (car Inno Setup n'est qu'un outil d'empaquetage 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é avec
nuitka --windows-console-mode=disable. (Sinon, une fenêtre noire apparaîtra après l'installation)- Haute performance : Veuillez confirmer que
--lto=yesa été utilisé. (Sinon, la vitesse de démarrage pourrait ne pas être idéale)- 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 des problèmes sur un système vierge.
Veuillez répondre 'Confirmé' si les fichiers sources sont prêts, sinon veuillez d'abord recompiler."
Étape 3 : Génération du Code Après confirmation de l'utilisateur, sortir le code incluant les métadonnées complètes et la correction de l'icône de désinstallation.
Compilation d'Optimisation Extrême avec Nuitka (Basée sur l'Expérience du Projet de Référence)
I. Stratégie de Choix entre 32 bits et 64 bits
Raison de l'utilisation de Python 32 bits par le projet de référence :
| Composant | Volume 64 bits | Volume 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 | Référence | -20~30% | - |
Conditions recommandées pour utiliser 32 bits :
- PASS : Occupation mémoire du programme < 2 Go
- PASS : Ne traite pas de très gros fichiers (< 2 Go)
- PASS : L'utilisateur cible a un ordinateur de bureau standard
Méthode de compilation 32 bits :
# 1. Installer Python 32 bits (peut coexister avec la version 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 (Validée par le Projet de Référence)
Liste d'exclusion sécurisée (non nécessaire au runtime) :
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. Optimisations Spécifiques aux Frameworks GUI
Optimisation Extrême de 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=icon.ico ^
--remove-output ^
main.py
Volume attendu : 80-120 Mo (après optimisation)
Optimisation 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
Volume attendu : 120-250 Mo (après optimisation)
IV. Modèle de Script de Compilation en Un Clic
Enregistrer sous build_optimized.bat (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 avec vos valeurs réelles) ===
set APP_NAME=VotreNomApp
set MAIN_FILE=main.py
set ICON_FILE=icon.ico
REM === Détection automatique du nombre de cœurs CPU ===
REM Utilise la variable d'environnement Windows (wmic supprimé dans Win11 22H2+ ; si non détecté, --jobs=0 fera une 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 des anciennes compilations...
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 des résultats 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 - Volume après compilation : %SIZE_MB% Mo
echo.
echo [4/4] Nettoyage de rétrécissement en cours (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 de Rétrécissement de 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 les erreurs silencieusement : les échecs de suppression seront affichés pour éviter les faux succès
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Nettoyage de rétrécissement de 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 du volume initial
$InitialSize = (Get-ChildItem -Path $DistPath -Recurse -File | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "`nVolume initial : $([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 docs/exemples..." -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 des bytecodes .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. Réduire les métadonnées .dist-info
Write-Host "`n[7/7] Réduction 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 au runtime par importlib.metadata, 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 à nettoyer trouvée (déjà optimisé)" -ForegroundColor Gray
}
# Statistiques du volume 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 "Nettoyage terminé !" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Volume initial : $([math]::Round($InitialSize, 2)) Mo" -ForegroundColor Yellow
Write-Host "Volume final : $([math]::Round($FinalSize, 2)) Mo" -ForegroundColor Green
Write-Host "Espace économisé : $([math]::Round($SavedSize, 2)) Mo ($([math]::Round($SavedPercent, 1))%)" -ForegroundColor Cyan
Write-Host "=============================="