fix: keep resource folders external alongside EXE instead of embedding

This commit is contained in:
Данил Ярош 2026-03-19 16:15:18 +03:00
parent 9b7933d2a0
commit 9ea3c32c64
8 changed files with 50 additions and 24 deletions

View File

@ -32,6 +32,7 @@ python -m pip install -r requirements-build.txt
Скрипт автоматически:
- очищает `build/`, `dist/`, `__pycache__/`
- запускает PyInstaller по `plate_config_app.spec`
- копирует папки `light_modes/`, `input_mappings/`, `commands/` в `dist/`
- выводит путь и размер готового EXE
### 3. Только очистка (без сборки)
@ -59,9 +60,19 @@ python -m pip install -r requirements-build.txt
| Ресурс | Описание |
|----------------------|---------------------------------|
| `light_modes/` | Файлы режимов подсветки (.lm) |
| `input_mappings/` | Маппинги входов (.mapping) |
| `commands/` | Наборы команд (.csv) |
| `qtawesome/` | Шрифты и charmap иконок |
Hidden imports: `qtawesome`, `Crypto.Cipher._raw_aes`, `Crypto.Util._raw_api`
## Ресурсы рядом с EXE
Скрипт `build_exe.ps1` после сборки копирует папки в `dist/`:
| Папка | Описание |
|--------------------|---------------------------------|
| `light_modes/` | Файлы режимов подсветки (.lm) |
| `input_mappings/` | Маппинги входов (.mapping) |
| `commands/` | Наборы команд (.csv) |
Эти файлы можно редактировать без пересборки — достаточно изменить их
рядом с EXE и перезапустить приложение.

View File

@ -172,9 +172,10 @@ health-check) вынесены в `QThread`-подклассы. Связь с UI
Создайте `.mapping` файл в `input_mappings/` в формате TOML.
Структура описана в `app/services/input_mappings_service.py`.
После добавления файлов они подхватятся при следующем запуске из исходников.
Для EXE-сборки необходимо пересобрать приложение (папки автоматически
включаются через `plate_config_app.spec`).
После добавления файлов они подхватятся при следующем запуске.
При сборке EXE папки автоматически копируются рядом с исполняемым файлом
скриптом `build_exe.ps1`. Пересборка для обновления конфигураций **не нужна** —
достаточно отредактировать файлы рядом с EXE и перезапустить приложение.
---
@ -189,4 +190,5 @@ health-check) вынесены в `QThread`-подклассы. Связь с UI
.\build_exe.ps1 -InstallBuildDeps
```
Результат: `dist\plate_config_app.exe`.
Результат: `dist\plate_config_app.exe` + папки `dist\light_modes\`,
`dist\input_mappings\`, `dist\commands\`.

View File

@ -111,8 +111,10 @@
| `input_mappings/` | `.mapping` | Маппинги входов по играм (формат TOML) |
| `commands/` | `.csv` | Наборы команд платы (разделитель `;`) |
Эти файлы встраиваются внутрь EXE при сборке. Для обновления конфигураций
необходима пересборка.
Эти файлы располагаются рядом с EXE (или в корне проекта при запуске из
исходников). При сборке они автоматически копируются в папку `dist/` рядом с
EXE. Можно редактировать файлы конфигураций без пересборки — достаточно
изменить нужный файл и перезапустить приложение.
---

View File

@ -32,11 +32,11 @@ class CommandSet:
def _get_commands_dir() -> Path:
"""Определить путь к папке commands/.
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
При запуске из исходников — рядом с корнем проекта.
"""
if getattr(sys, "frozen", False):
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
base = Path(sys.executable).parent
else:
base = Path(__file__).resolve().parent.parent.parent
return base / "commands"

View File

@ -41,11 +41,11 @@ class InputMapping:
def _get_input_mappings_dir() -> Path:
"""Определить путь к папке input_mappings/.
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
При запуске из исходников — рядом с корнем проекта.
"""
if getattr(sys, "frozen", False):
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
base = Path(sys.executable).parent
else:
base = Path(__file__).resolve().parent.parent.parent
return base / "input_mappings"

View File

@ -34,13 +34,12 @@ class LightMode:
def _get_light_modes_dir() -> Path:
"""Определить путь к папке light_modes/.
При запуске из .exe (PyInstaller onefile) — в распакованном каталоге _MEIPASS.
При запуске из .exe (PyInstaller) — рядом с exe-файлом.
При запуске из исходников — рядом с корнем проекта.
"""
if getattr(sys, "frozen", False):
base = Path(getattr(sys, "_MEIPASS", Path(sys.executable).parent))
base = Path(sys.executable).parent
else:
# Разработка: корень проекта (где лежит main.py)
base = Path(__file__).resolve().parent.parent.parent
return base / "light_modes"

View File

@ -58,10 +58,25 @@ if ($LASTEXITCODE -ne 0) {
}
$exe = Join-Path $projectRoot "dist\plate_config_app.exe"
if (Test-Path $exe) {
$size = [math]::Round((Get-Item $exe).Length / 1MB, 1)
Write-Host ""
Write-Host "Сборка завершена: $exe ($size MB)"
} else {
if (-not (Test-Path $exe)) {
throw "EXE не найден после сборки."
}
# ── Копирование ресурсных папок рядом с EXE ───────────────────────
Write-Host ""
Write-Host "=== Копирование ресурсов ==="
$resourceFolders = @("light_modes", "input_mappings", "commands")
foreach ($folder in $resourceFolders) {
$src = Join-Path $projectRoot $folder
$dst = Join-Path $projectRoot "dist\$folder"
if (Test-Path $src) {
Copy-Item $src -Destination $dst -Recurse -Force
Write-Host " Скопировано: $folder"
} else {
Write-Host " Пропущено (не найдено): $folder" -ForegroundColor Yellow
}
}
$size = [math]::Round((Get-Item $exe).Length / 1MB, 1)
Write-Host ""
Write-Host "Сборка завершена: $exe ($size MB)"

View File

@ -11,9 +11,6 @@ a = Analysis(
pathex=[],
binaries=[],
datas=[
('light_modes', 'light_modes'),
('input_mappings', 'input_mappings'),
('commands', 'commands'),
(_qta_dir, 'qtawesome'),
],
hiddenimports=[