这是使用PyQT5作为UI的首次提交,将后端和UI合并到1个工程中,统一使用了Python,没有使用JS和HTML
This commit is contained in:
328
UI/build_spec_example.py
Normal file
328
UI/build_spec_example.py
Normal file
@@ -0,0 +1,328 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user