Files
dtm-py-all/UI/build_spec_example.py

329 lines
7.3 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
PyInstaller 打包配置生成器
使用方法:
1. 将此文件复制到后台工程根目录
2. 运行: python build_spec_example.py
3. 会生成三个 .spec 文件:
- build_backend.spec : 打包后台服务
- build_frontend.spec : 打包 GUI 前端
- build_all.spec : 统一打包
4. 执行打包:
pyinstaller build_backend.spec
pyinstaller build_frontend.spec
pyinstaller build_all.spec
"""
import os
# ============== 后台服务打包配置 ==============
BACKEND_SPEC = """# -*- mode: python ; coding: utf-8 -*-
# DTM 后台服务打包配置
block_cipher = None
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[
('backend', 'backend'),
('config', 'config'),
# 添加其他需要的资源文件
],
hiddenimports=[
'flask',
'flask_socketio',
'flask_cors',
'sqlite3',
'requests',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='dtm_backend',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True, # 显示控制台,便于查看日志
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='dtm_backend',
)
"""
# ============== GUI 前端打包配置 ==============
FRONTEND_SPEC = """# -*- mode: python ; coding: utf-8 -*-
# DTM GUI 前端打包配置
block_cipher = None
a = Analysis(
['frontend_gui/dtmgtUI.py'],
pathex=[],
binaries=[],
datas=[
('frontend_gui/styles', 'styles'),
('frontend_gui/qml', 'qml'),
# 如果有图标、图片等资源,也添加进来
# ('frontend_gui/resources', 'resources'),
],
hiddenimports=[
'PyQt5',
'PyQt5.QtCore',
'PyQt5.QtGui',
'PyQt5.QtWidgets',
'PyQt5.QtWebEngineWidgets',
'PyQt5.QtQml',
'requests',
'websocket',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='dtm_gui',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False, # GUI 程序不显示控制台
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='frontend_gui/icon.ico', # 如果有图标文件
)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='dtm_gui',
)
"""
# ============== 统一打包配置 ==============
ALL_SPEC = """# -*- mode: python ; coding: utf-8 -*-
# DTM 完整系统打包配置(后台 + 前端)
block_cipher = None
# ========== 后台服务分析 ==========
backend_a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[
('backend', 'backend'),
('config', 'config'),
],
hiddenimports=[
'flask',
'flask_socketio',
'flask_cors',
'sqlite3',
'requests',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
# ========== GUI 前端分析 ==========
frontend_a = Analysis(
['frontend_gui/dtmgtUI.py'],
pathex=[],
binaries=[],
datas=[
('frontend_gui/styles', 'frontend_gui/styles'),
('frontend_gui/qml', 'frontend_gui/qml'),
],
hiddenimports=[
'PyQt5',
'PyQt5.QtCore',
'PyQt5.QtGui',
'PyQt5.QtWidgets',
'PyQt5.QtWebEngineWidgets',
'PyQt5.QtQml',
'requests',
'websocket',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
# ========== 合并分析结果 ==========
MERGE((backend_a, 'backend', 'backend'), (frontend_a, 'frontend', 'frontend'))
# ========== 后台 EXE ==========
backend_pyz = PYZ(backend_a.pure, backend_a.zipped_data, cipher=block_cipher)
backend_exe = EXE(
backend_pyz,
backend_a.scripts,
[],
exclude_binaries=True,
name='dtm_backend',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
# ========== 前端 EXE ==========
frontend_pyz = PYZ(frontend_a.pure, frontend_a.zipped_data, cipher=block_cipher)
frontend_exe = EXE(
frontend_pyz,
frontend_a.scripts,
[],
exclude_binaries=True,
name='dtm_gui',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='frontend_gui/icon.ico',
)
# ========== 收集所有文件 ==========
coll = COLLECT(
backend_exe,
backend_a.binaries,
backend_a.datas,
frontend_exe,
frontend_a.binaries,
frontend_a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='DTM_System',
)
"""
def generate_specs():
"""生成打包配置文件"""
specs = {
'build_backend.spec': BACKEND_SPEC,
'build_frontend.spec': FRONTEND_SPEC,
'build_all.spec': ALL_SPEC,
}
print("=== PyInstaller 配置生成器 ===\n")
for filename, content in specs.items():
filepath = os.path.join(os.getcwd(), filename)
# 检查文件是否存在
if os.path.exists(filepath):
response = input(f"文件 {filename} 已存在,是否覆盖?(y/N): ")
if response.lower() != 'y':
print(f" 跳过 {filename}")
continue
# 写入文件
with open(filepath, 'w', encoding='utf-8') as f:
f.write(content)
print(f"✓ 已生成: {filename}")
print("\n=== 使用说明 ===")
print("1. 打包后台服务:")
print(" pyinstaller build_backend.spec")
print()
print("2. 打包 GUI 前端:")
print(" pyinstaller build_frontend.spec")
print()
print("3. 统一打包(后台+前端):")
print(" pyinstaller build_all.spec")
print()
print("4. 打包产物位于 dist/ 目录")
print()
print("注意事项:")
print("- 确保已安装 PyInstaller: pip install pyinstaller")
print("- 根据实际项目结构调整 .spec 文件中的路径和依赖")
print("- 打包前建议在虚拟环境中测试")
print()
if __name__ == '__main__':
generate_specs()