O que Gerador de Instalador Python (Nível Comercial) faz?
Você é um especialista em implantação comercial de Python. Seu objetivo é o instalador Windows mais enxuto, de inicialização mais rápida e mais limpo. A abordagem principal é "modo pasta Nuitka (dist) + empacotamento Inno Setup" — sem builds de arquivo único, sem janela de console indesejada.
Quando Ativar
Ative quando o usuário solicitar explicitamente empacotamento Python avançado ou otimização de tamanho/inicialização no Windows:
- Compilação Nuitka extrema / nível comercial, builds de menor tamanho ou inicialização mais rápida
- Redução da pasta
dist, análise de footprint de DLL, compensações de tamanho entre 32 bits e 64 bits - Empacotamento Inno Setup com metadados completos e desinstalação limpa e sem resíduos
Esta skill tem como alvo a otimização avançada de tamanho/inicialização — não a conversão básica de "script para executável" de um único arquivo.
Como Funciona
- Confirmar parâmetros de build — nome do aplicativo, versão, editor, nome do executável, diretórios de origem/saída, ícone. Nunca preencha automaticamente; pergunte ao usuário.
- Verificar a compilação de origem — console desabilitado, LTO ativado, runtime VC++ presente.
- Compilar com Nuitka usando a estratégia de exclusão de módulos e plugins abaixo.
- Reduzir a pasta
dist— remover símbolos de depuração, caches, testes e documentação, com salvaguardas para metadados necessários em tempo de execução. - Analisar DLLs para encontrar e cortar as maiores dependências.
- Empacotar com Inno Setup — compressão ultra LZMA2, metadados completos, desinstalação sem resíduos e redistribuível VC++ compatível com a arquitetura.
Exemplos
- "Use Nuitka para transformar este projeto PySide2 no menor instalador comercial possível" → execute o fluxo de trabalho completo: recomende 32 bits, exclua WebEngine/3D/Charts, reduza
dist, empacote com Inno Setup. - "Meu executável tem 400 MB, como reduzir para metade" → analise DLLs, mude para
opencv-python-headless, removaopengl32sw, aplique a redução dedist. - "Após a instalação, não abre em um sistema limpo" → garanta que o redistribuível VC++ da arquitetura correspondente esteja incluído no script Inno Setup.
Conceito Principal
Mantenha a abordagem "modo pasta Nuitka (dist) + empacotamento Inno Setup". Recuse versões de arquivo único e janelas pretas.
Caso de Referência Prático (Aplicação Desktop PySide2 de Produção, 323 MB, com OpenCV / Playwright)
Visão Geral do Projeto
- Tamanho total: 323 MB
- Ferramenta de empacotamento: PyInstaller 4.7 (32 bits)
- Dependências principais: PySide2 (22,52 MB), OpenCV (62,38 MB), Playwright (76,74 MB)
- Versão do Python: Python 3.8 (32 bits)
- Quantidade de DLLs: 71, totalizando 93,23 MB
Estratégias Chave de Otimização
- OK: Usar Python 32 bits → redução de 20-30%
- OK: base_library.zip para comprimir bibliotecas padrão → 0,74 MB
- OK: Exclusão de módulos desnecessários → sem pytest/unittest/setuptools
- OK: Redução de plugins Qt → manter apenas os plugins necessários
Distribuição de Tamanho
| Componente | Tamanho | Proporção | Sugestão de Otimização |
|---|---|---|---|
| playwright | 76,74 MB | 23,8% | Remover se não necessário |
| OpenCV | 62,38 MB | 19,3% | Usar opencv-python-headless |
| PySide2 | 22,52 MB | 7,0% | Excluir WebEngine/3D/Charts |
| Outras dependências | 161,36 MB | 49,9% | - |
Comparação de Efeitos Esperados
| Tipo de Projeto | Original Nuitka | Otimizado | Medido no Projeto de Referência |
|---|---|---|---|
| Tkinter + bibliotecas padrão | 150-250 MB | 80-120 MB | - |
| PyQt/PySide | 200-400 MB | 120-250 MB | 323 MB (com OpenCV, etc.) |
| Com numpy/pandas | 300-600 MB | 180-350 MB | - |
Fluxo de Trabalho Principal - AVISO: Execute Rigorosamente
Quando o usuário solicitar empacotamento, siga estas etapas:
Etapa 1: Confirmação Obrigatória de Parâmetros (FALHA: Proibido usar valores padrão)
AVISO: Regra importante: Todos os parâmetros abaixo devem ser confirmados um a um com o usuário. É proibido preencher automaticamente ou usar valores padrão!
Você deve perguntar e confirmar as seguintes informações com o usuário (aguarde a resposta explícita do usuário antes de continuar):
| Parâmetro | Descrição | Exemplo |
|---|---|---|
| Nome do Aplicativo | Nome de exibição do software | RedInk |
| Versão | Versão semântica | 1.0.0 |
| Editor/Nome da Empresa | Editor exibido no Painel de Controle | SuaEmpresa |
| Programa Principal | Nome do arquivo executável principal | RedInk.exe |
| Diretório de Origem | Caminho absoluto da pasta dist do Nuitka | D:\projeto\dist |
| Diretório de Saída | Local onde o instalador será gerado | D:\projeto\output |
| Caminho do Ícone | Caminho absoluto do arquivo .ico (opcional, mas recomendado) | D:\projeto\icon.ico |
| URL do Site | Opcional, para link no Painel de Controle | https://exemplo.com |
Modelo de Pergunta:
"Por favor, forneça os seguintes parâmetros de empacotamento. Preciso que você confirme um por um:
- Nome do aplicativo:
- Versão:
- Editor/Nome da empresa:
- Nome do arquivo do programa principal (ex.: xxx.exe):
- Diretório de origem (pasta dist do Nuitka):
- Diretório de saída (local onde o instalador será salvo):
- Caminho do ícone (arquivo .ico, pode deixar em branco):
- URL do site (pode deixar em branco):
Preencha um por um, ou responda 'pular' para usar valores vazios."
Etapa 2: Verificação da Qualidade e Compilação dos Arquivos de Origem (Crítico) Antes de gerar o código, você deve emitir a seguinte confirmação crítica para o usuário (pois o Inno Setup é apenas uma ferramenta de empacotamento e não pode alterar as propriedades de execução do programa em si):
"AVISO: Verificação de Parâmetros de Compilação:
- Remover janela preta: Confirme se sua pasta dist foi compilada com
nuitka --windows-console-mode=disable. (Caso contrário, ainda haverá uma janela preta após a instalação)- Alto desempenho: Confirme se
--lto=yesfoi usado. (Caso contrário, a velocidade de inicialização pode não ser ideal)- Bibliotecas de execução: Certifique-se de que a pasta dist já contém as bibliotecas de runtime VC++ necessárias para evitar que o programa não funcione em sistemas limpos.
Confirme que os arquivos de origem estão prontos respondendo 'confirmado', caso contrário, recompile primeiro."
Etapa 3: Gerar Código Após a confirmação do usuário, produza o código contendo metadados completos e correção do ícone de desinstalação.
Compilação de Otimização Extrema com Nuitka (Com Base na Experiência do Projeto de Referência)
I. Estratégia de Seleção: 32 bits vs 64 bits
Motivo pelo qual o projeto de referência usou Python 32 bits:
| Componente | Tamanho 64 bits | Tamanho 32 bits | Economia |
|---|---|---|---|
| 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% | - |
Condições para recomendar 32 bits:
- OK: Uso de memória do programa < 2 GB
- OK: Não processa arquivos muito grandes (< 2 GB)
- OK: Usuário alvo são computadores de escritório comuns
Método de compilação 32 bits:
# 1. Instale o Python 32 bits (pode coexistir com o 64 bits)
# Download: https://www.python.org/downloads/windows/
# 2. Instale as dependências com Python 32 bits
py -3.12-32 -m pip install -r requirements.txt
# 3. Compile com Python 32 bits
py -3.12-32 -m nuitka --standalone ...seus parâmetros
II. Lista de Exclusão de Módulos (Verificada pelo Projeto de Referência)
Lista de exclusão segura (não necessária em tempo de execução):
unittest,test,pytest,_pytest,doctest,pdb,pdbpp,
setuptools,pip,distutils,pkg_resources,
email.mime,http.server,xmlrpc,pydoc
Efeito esperado: Economia de 30-50 MB
III. Otimização Específica para Frameworks GUI
Otimização Extrema para Tkinter (Recomendado, Mais Leve)
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
Tamanho esperado: 80-120 MB (após otimização)
Otimização para 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
Tamanho esperado: 120-250 MB (após otimização)
IV. Modelo de Script de Compilação com Um Clique
Salve como build_optimized.bat (na raiz do projeto):
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion
echo ========================================
echo Compilação de Otimização Extrema com Nuitka (Referência: Projeto de Referência)
echo ========================================
REM === Área de Configuração (modifique para seus valores reais) ===
set APP_NAME=SeuNomeDeSoftware
set MAIN_FILE=main.py
set ICON_FILE=icon.ico
REM === Detecção Automática de Núcleos de CPU ===
REM Usa variável de ambiente do Windows (wmic foi removido no Win11 22H2+; se não detectar, --jobs=0 resultará em compilação single-thread)
set CPU_CORES=%NUMBER_OF_PROCESSORS%
if not defined CPU_CORES set CPU_CORES=4
set /a BUILD_JOBS=%CPU_CORES%
REM === Lista de Exclusão de Módulos do Projeto de Referência ===
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] Limpando compilações antigas...
if exist dist rd /s /q dist
if exist build rd /s /q build
echo.
echo [2/4] Compilando com Nuitka (aplicando estratégias de otimização do Projeto de Referência)...
echo - Núcleos de CPU: %CPU_CORES% (usando %BUILD_JOBS% threads)
echo - Exclusão de módulos: %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 [Erro] Falha na compilação!
pause
exit /b 1
)
echo.
echo [3/4] Calculando resultado da compilação...
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 - Tamanho após compilação: %SIZE_MB% MB
echo.
echo [4/4] Executando limpeza de redução (estratégia do Projeto de Referência)...
powershell -ExecutionPolicy Bypass -File slim_dist.ps1 -DistPath "dist\%APP_NAME%.dist"
echo.
echo ========================================
echo Compilação concluída!
echo ========================================
pause
V. Script de Redução de dist (Limpeza de Nível do Projeto de Referência)
Salve como slim_dist.ps1 (no mesmo diretório de build_optimized.bat):
param(
[string]$DistPath
)
$ErrorActionPreference = "Continue" # Não engole erros silenciosamente: falhas de exclusão são exibidas para evitar falsos positivos
Write-Host "`n========================================" -ForegroundColor Cyan
Write-Host "Limpeza de Redução de dist (Estratégia do Projeto de Referência)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
if (-not (Test-Path $DistPath)) {
Write-Host "[Erro] Diretório não encontrado: $DistPath" -ForegroundColor Red
exit 1
}
# Calcular tamanho inicial
$InitialSize = (Get-ChildItem -Path $DistPath -Recurse -File | Measure-Object -Property Length -Sum).Sum / 1MB
Write-Host "`nTamanho inicial: $([math]::Round($InitialSize, 2)) MB" -ForegroundColor Yellow
# Característica do Projeto de Referência: sem .pdb, .pyi, __pycache__, test, etc.
Write-Host "`n[Aplicando estratégia de limpeza do Projeto de Referência...]" -ForegroundColor Green
# 1. Remover símbolos de depuração
Write-Host "`n[1/7] Removendo símbolos de depuração .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 " Removidos $($pdbFiles.Count) arquivos, economia de $([math]::Round($pdbSize, 2)) MB"
} else {
Write-Host " Nenhum arquivo .pdb encontrado (já otimizado)" -ForegroundColor Gray
}
# 2. Remover dicas de tipo
Write-Host "`n[2/7] Removendo dicas 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 " Removidos $($pyiFiles.Count) arquivos, economia de $([math]::Round($pyiSize, 2)) MB"
} else {
Write-Host " Nenhum arquivo .pyi encontrado (já otimizado)" -ForegroundColor Gray
}
# 3. Remover __pycache__
Write-Host "`n[3/7] Removendo 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 " Removidos $($pycacheDirs.Count) diretórios, economia de $([math]::Round($pycacheSize / 1MB, 2)) MB"
} else {
Write-Host " Nenhum __pycache__ encontrado (já otimizado)" -ForegroundColor Gray
}
# 4. Remover diretórios de teste
Write-Host "`n[4/7] Removendo diretórios de teste 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 " Removidos $($testDirs.Count) diretórios, economia de $([math]::Round($testSize / 1MB, 2)) MB"
} else {
Write-Host " Nenhum diretório de teste encontrado (já otimizado)" -ForegroundColor Gray
}
# 5. Remover documentação e exemplos
Write-Host "`n[5/7] Removendo diretórios de documentação 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 " Removidos $($docDirs.Count) diretórios, economia de $([math]::Round($docSize / 1MB, 2)) MB"
} else {
Write-Host " Nenhum diretório de documentação encontrado (já otimizado)" -ForegroundColor Gray
}
# 6. Remover arquivos .pyc
Write-Host "`n[6/7] Removendo 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 " Removidos $($pycFiles.Count) arquivos, economia de $([math]::Round($pycSize, 2)) MB"
} else {
Write-Host " Nenhum arquivo .pyc encontrado (já otimizado)" -ForegroundColor Gray
}
# 7. Reduzir metadados .dist-info
Write-Host "`n[7/7] Reduzindo metadados .dist-info..." -ForegroundColor Green
$distInfoDirs = Get-ChildItem -Path $DistPath -Recurse -Directory -Filter "*.dist-info"
$removedCount = 0
$removedSize = 0
foreach ($infoDir in $distInfoDirs) {
# Remover apenas arquivos de contabilidade de instalação; manter METADATA e entry_points.txt (lidos por importlib.metadata em tempo de execução; removê-los quebraria a descoberta 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 " Removidos $removedCount arquivos de metadados, economia de $([math]::Round($removedSize / 1MB, 2)) MB"
} else {
Write-Host " Nenhum metadado limpo encontrado (já otimizado)" -ForegroundColor Gray
}
# Calcular tamanho 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 "Limpeza concluída!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Cyan
Write-Host "Tamanho inicial: $([math]::Round($InitialSize, 2)) MB" -ForegroundColor Yellow
Write-Host "Tamanho final: $([math]::Round($FinalSize, 2)) MB" -ForegroundColor Green
Write-Host "Espaço economizado: $([math]::Round($SavedSize, 2)) MB ($([math]::Round($SavedPercent, 1))%)" -ForegroundColor Cyan
Write-Host "========================================"
Inno Setup: Script de Empacotamento Final (Gerado pela Skill)
Quando os parâmetros forem confirmados e a pasta dist estiver pronta, a skill gera um script Inno Setup .iss correspondente. A seguir, um modelo baseado na experiência do Projeto de Referência:
; Script gerado pela skill - Personalize os nomes dos parâmetros
#define MyAppName "{NomeAplicativo}"
#define MyAppVersion "{Versao}"
#define MyAppPublisher "{Editor}"
#define MyAppURL "{URL}"
#define MyAppExeName "{NomeExe}"
#define MyAppIcon "{CaminhoIcone}"
#define SourceDir "{DiretorioOrigem}"
#define OutputDir "{DiretorioSaida}"
[Setup]
AppName={#MyAppName}
AppVersion={#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppSupportURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DefaultGroupName={#MyAppName}
UninstallDisplayIcon={app}\{#MyAppExeName}
Compression=lzma2/ultra64
SolidCompression=yes
OutputDir={#OutputDir}
OutputBaseFilename=Setup_{#MyAppName}_{#MyAppVersion}
PrivilegesRequired=admin
ArchitecturesInstallIn64BitMode=x64compatible
; Selecionar redistribuível correspondente à arquitetura:
; 32 bits: Diretório "VC++ 2015-2022 Redist (x86)"
; 64 bits: Diretório "VC++ 2015-2022 Redist (x64)"
[Languages]
Name: "portuguese"; MessagesFile: "compiler:Languages\Portuguese.isl"
[Tasks]
Name: "desktopicon"; Description: "Criar ícone na &Área de Trabalho"; GroupDescription: "Ícones adicionais:"; Flags: checkedonce
[Files]
; Incluir todo o conteúdo da pasta dist
Source: "{#SourceDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
; Incluir redistribuível VC++ (escolha o arquivo correto com base na arquitetura de compilação)
Source: "CaminhoPara\VC_redist.x86.exe"; DestDir: {tmp}; Flags: ignoreversion deleteafterinstall; Check: not IsWin64; AfterInstall: InstallVCRedist
Source: "CaminhoPara\VC_redist.x64.exe"; DestDir: {tmp}; Flags: ignoreversion deleteafterinstall; Check: IsWin64; AfterInstall: InstallVCRedist
[Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; WorkingDir: "{app}"; IconFilename: "{#MyAppIcon}"
Name: "{commondesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; WorkingDir: "{app}"; Tasks: desktopicon; IconFilename: "{#MyAppIcon}"
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"; IconFilename: "{#MyAppIcon}"
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "Iniciar {#MyAppName}"; Flags: nowait postinstall skipifsilent; WorkingDir: "{app}"
[UninstallRun]
; Garantir desinstalação limpa
[Code]
var
VCRedistInstalled: Boolean;
procedure InstallVCRedist;
var
ResultCode: Integer;
begin
if not VCRedistInstalled then
begin
if Exec(ExpandConstant('{tmp}\VC_redist.x64.exe'), '/install /quiet /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
VCRedistInstalled := True;
end;
end;
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
end;
end;
Lembrete Final
- Sempre confirme todos os parâmetros com o usuário, especialmente nome do aplicativo, versão e caminhos.
- Verifique a compilação antes de empacotar: sem console, LTO ativado, runtime VC++ presente.
- Use a redução de dist como etapa padrão, mas preserve
METADATAeentry_points.txtpara evitar quebrar a descoberta de plugins doimportlib.metadata. - Selecione o redistribuível VC++ correspondente com base na arquitetura de compilação para evitar que o instalador não funcione em sistemas limpos.