nuitka 打包 pySide 软件
第一步:打开下面的软件(因为pySide 有组件依赖于 VS 2022 C++ 相关构建工具)

第二步:查找并切换到你工程对应的 python 环境(我用的是 conda)

第三步:切换到你工程所在的目录

第四步:执行 python 打包脚本,开始打包

我的pySide 打包脚本如下:
"""
优化版打包脚本 - 支持 PyInstaller 和 Nuitka 双模式
运行: python build_optimized.py [--use-nuitka]
"""
import os
import sys
import shutil
import subprocess
from pathlib import Path
import time
import argparse
import platform
def clean_build():
"""清理旧的构建文件"""
dirs_to_clean = ['build', 'dist', 'BuzzerTest.build', 'BuzzerTest.dist']
for dir_name in dirs_to_clean:
if os.path.exists(dir_name):
print(f"🧹 Cleaning {dir_name}...")
try:
shutil.rmtree(dir_name)
except PermissionError:
print(f" ⚠️ 无法删除 {dir_name},等待2秒后重试...")
time.sleep(2)
try:
shutil.rmtree(dir_name)
except Exception as e:
print(f" ⚠️ 仍然无法删除: {e}")
return False
# 清理spec文件
for f in Path('.').glob('*.spec'):
try:
f.unlink()
except:
pass
return True
def check_requirements():
"""检查构建环境"""
print("\n🔍 检查构建环境...")
# 检查Python版本
print(f" Python: {sys.version}")
# 检查必要的包
required_packages = {
'pyinstaller': 'PyInstaller',
'pyserial': 'serial',
#'PySide6': 'PySide6',
'pyside6': 'PySide6', # 改为 pyside6
'pandas': 'pandas',
'openpyxl': 'openpyxl'
}
missing = []
for pkg, import_name in required_packages.items():
try:
__import__(import_name)
print(f" ✅ {pkg}")
except ImportError:
print(f" ❌ {pkg} (未安装)")
missing.append(pkg)
if missing:
print(f"\n ⚠️ 缺少以下包: {', '.join(missing)}")
install = input(" 是否自动安装? (y/n): ").lower().strip()
if install == 'y':
for pkg in missing:
print(f" 安装 {pkg}...")
subprocess.run([sys.executable, '-m', 'pip', 'install', pkg], check=False)
else:
print(" 请手动安装后重试")
return False
# 检查Nuitka (如果启用)
if args.use_nuitka:
try:
__import__('nuitka')
print(" ✅ Nuitka")
except ImportError:
print(" ❌ Nuitka (未安装)")
install = input(" 是否安装 Nuitka? (y/n): ").lower().strip()
if install == 'y':
subprocess.run([sys.executable, '-m', 'pip', 'install', 'nuitka'], check=False)
print(" 请重新运行脚本")
return False
else:
print(" 将使用 PyInstaller 模式")
return False
# 检查C++编译器 (Windows)
if platform.system() == 'Windows':
try:
subprocess.run(['cl'], capture_output=True, check=False)
print(" ✅ C++ 编译器 (MSVC)")
except FileNotFoundError:
print(" ❌ 未找到 C++ 编译器")
print(" 请安装 Visual Studio Build Tools:")
print(" https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022")
print(" 或使用 --no-nuitka 选项")
return False
return True
def ensure_files():
"""确保必要的文件存在"""
required_files = ['ibuzzertest_pyside.py', 'style_red_white.css', 'buzz_ico.ico']
missing = []
for f in required_files:
if not os.path.exists(f):
missing.append(f)
if missing:
print(f"❌ 缺少必要文件: {', '.join(missing)}")
return False
print("✅ 所有必要文件已就绪")
return True
def build_with_pyinstaller():
"""使用 PyInstaller 打包"""
print("\n📦 使用 PyInstaller 打包...")
cmd = [
sys.executable, '-m', 'PyInstaller',
'--name=BuzzerTest',
'--windowed',
'--onefile',
'--clean',
'--noconfirm',
'--add-data=style_red_white.css;.',
'--add-data=buzz_ico.ico;.',
'--icon=buzz_ico.ico',
'--runtime-tmpdir=%TEMP%',
'--hidden-import=pandas',
'--hidden-import=pandas.io.excel',
'--hidden-import=openpyxl',
'--hidden-import=serial',
'--hidden-import=serial.tools',
'--hidden-import=serial.tools.list_ports',
'--hidden-import=PySide6',
'--hidden-import=PySide6.QtCore',
'--hidden-import=PySide6.QtGui',
'--hidden-import=PySide6.QtWidgets',
'ibuzzertest_pyside.py'
]
try:
result = subprocess.run(cmd, capture_output=False, check=True)
return True
except subprocess.CalledProcessError as e:
print(f"❌ PyInstaller 打包失败: {e}")
return False
def build_with_nuitka():
"""使用 Nuitka 打包 (启动更快, 体积更小)"""
print("\n🚀 使用 Nuitka 打包...")
print(" 首次编译可能需要5-15分钟,请耐心等待")
cmd = [
sys.executable, '-m', 'nuitka',
'--standalone',
'--windows-disable-console',
'--windows-icon-from-ico=buzz_ico.ico',
'--output-dir=dist',
'--output-filename=BuzzerTest.exe',
'--enable-plugin=pyside6',
'--include-package=pandas',
'--include-package=openpyxl',
'--include-package=serial',
'--include-data-files=style_red_white.css=style_red_white.css',
'--include-data-files=buzz_ico.ico=buzz_ico.ico',
'ibuzzertest_pyside.py'
]
try:
# 改为 capture_output=True 来捕获错误信息
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
print(result.stdout)
return True
except subprocess.CalledProcessError as e:
print(f"❌ Nuitka 打包失败: {e}")
print("\n========== 错误输出 ==========")
print(e.stderr)
print("===============================")
return False
def reorganize_nuitka_output():
"""整理 Nuitka 输出:EXE 移到根目录,其他文件移到 _internal/"""
dist_dir = Path('dist')
# Nuitka 生成的文件夹名是 ibuzzertest_pyside.dist
exe_dir = dist_dir / 'ibuzzertest_pyside.dist'
exe_file = exe_dir / 'ibuzzertest_pyside.exe' # Nuitka 生成的文件名
if not exe_dir.exists() or not exe_file.exists():
print(f"⚠️ 未找到 Nuitka 输出目录: {exe_dir}")
return False
print("\n📁 整理 Nuitka 文件结构...")
# 创建 _internal 目录
internal_dir = dist_dir / '_internal'
internal_dir.mkdir(exist_ok=True)
# 移动所有文件到 _internal(除了 EXE)
moved_count = 0
for item in exe_dir.iterdir():
if item.name == 'ibuzzertest_pyside.exe':
continue
try:
shutil.move(str(item), str(internal_dir / item.name))
moved_count += 1
except Exception as e:
print(f" ⚠️ 移动 {item.name} 失败: {e}")
# 将 EXE 重命名为 BuzzerTest.exe 并移到 dist 根目录
dest_exe = dist_dir / 'BuzzerTest.exe'
try:
shutil.move(str(exe_file), str(dest_exe))
print(f" ✅ EXE: ibuzzertest_pyside.exe -> BuzzerTest.exe")
except Exception as e:
print(f" ⚠️ 移动 EXE 失败: {e}")
return False
# 删除空的目录
try:
exe_dir.rmdir()
print(f" 🗑️ 删除空目录: ibuzzertest_pyside.dist/")
except OSError:
shutil.rmtree(exe_dir)
print(f" 🗑️ 删除目录: ibuzzertest_pyside.dist/")
print(f" ✅ 整理完成: 移动了 {moved_count} 个文件到 _internal/")
return True
def create_readme(build_type='PyInstaller'):
"""创建使用说明文件"""
readme_content = f"""
BuzzerTest 使用说明 (使用 {build_type} 打包)
=============================================
📌 系统要求
-----------
- Windows 7 / 8 / 10 / 11
- 无需安装 Python 或任何依赖
🚀 快速开始
-----------
1. 双击运行 BuzzerTest.exe
2. 选择串口并点击 CONNECT
3. 调整频率/电压/时长等参数
4. 点击 PLAY 开始测试
📁 文件说明
-----------
BuzzerTest.exe - 主程序
style_red_white.css - 样式文件(必须与exe在同一目录)
buzz_ico.ico - 程序图标
⚠️ 常见问题
-----------
1. 如果提示缺少 DLL,请安装:
https://aka.ms/vs/17/release/vc_redist.x64.exe
2. 串口无法连接:
- 检查设备是否已连接
- 检查串口号是否正确
- 检查是否有其他程序占用串口
3. Excel 导入功能:
- 需要 Excel 文件包含列:Freq/Hz, Is Muted, Duration/ms
- 支持 .xlsx 和 .xls 格式
💡 性能说明
-----------
- {build_type} 模式打包
- 启动速度: {'极快 (原生编译)' if build_type == 'Nuitka' else '较快 (解压启动)'}
版本: v1.0
生成日期: {time.strftime('%Y-%m-%d')}
"""
readme_path = os.path.join('dist', '使用说明.txt')
with open(readme_path, 'w', encoding='utf-8') as f:
f.write(readme_content)
print(f"📄 已创建使用说明: {readme_path}")
def test_executable():
"""测试生成的可执行文件"""
exe_paths = [
os.path.join('dist', 'BuzzerTest', 'BuzzerTest.exe'), # onedir模式
os.path.join('dist', 'BuzzerTest.exe'), # onefile模式 / Nuitka
]
for path in exe_paths:
if os.path.exists(path):
size_mb = os.path.getsize(path) / (1024 * 1024)
print(f"\n📁 文件位置: {os.path.abspath(path)}")
print(f"📊 文件大小: {size_mb:.2f} MB")
return True
return False
def main():
global args
parser = argparse.ArgumentParser(description='BuzzerTest 打包工具')
parser.add_argument('--use-nuitka', action='store_true',
help='使用 Nuitka 打包 (启动更快,但编译时间长)')
parser.add_argument('--no-nuitka', dest='use_nuitka', action='store_false',
help='强制使用 PyInstaller')
parser.set_defaults(use_nuitka=False)
args = parser.parse_args()
# 切换到脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
os.chdir(script_dir)
print("=" * 70)
print(" 🚀 BuzzerTest 优化打包工具 v3.0")
print(f" 模式: {'Nuitka (编译优化)' if args.use_nuitka else 'PyInstaller (标准打包)'}")
print("=" * 70)
print()
# 检查环境
if not check_requirements():
print("\n⚠️ 环境检查失败")
input("\n按 Enter 键退出...")
return
# 检查文件
if not ensure_files():
input("\n按 Enter 键退出...")
return
# 清理旧构建
print("\n🧹 清理旧构建...")
if not clean_build():
print("⚠️ 清理失败,请手动删除 build 和 dist 文件夹后重试")
input("\n按 Enter 键退出...")
return
# 选择打包方式
success = False
build_type = 'PyInstaller'
if args.use_nuitka:
print("\n🔥 使用 Nuitka 优化模式")
print(" 优点: 启动速度快3-5倍,体积更小")
print(" 缺点: 首次编译需要5-15分钟")
confirm = input("\n 确认使用 Nuitka? (y/n): ").lower().strip()
if confirm == 'y':
success = build_with_nuitka()
if success:
reorganize_nuitka_output() # 整理 Nuitka 输出
build_type = 'Nuitka'
else:
print(" 切换到 PyInstaller 模式")
success = build_with_pyinstaller()
else:
print("\n📦 使用 PyInstaller 标准模式")
success = build_with_pyinstaller()
if success:
print("\n" + "=" * 70)
print(" 🎉 打包完成!")
print("=" * 70)
if test_executable():
create_readme(build_type)
print("\n📦 分发文件清单:")
print(" - dist/ 目录下的所有文件")
print(" - 使用说明.txt")
if build_type == 'Nuitka':
print("\n⚡ 性能优势:")
print(" - 启动速度: 提升3-5倍")
print(" - 内存占用: 减少30-50%")
print(" - 用户体验: 接近原生程序")
else:
print("\n⚠️ 未找到生成的可执行文件")
else:
print("\n❌ 打包失败,请检查上面的错误信息")
print("\n可能的原因:")
print("1. 请确保以管理员身份运行")
print("2. 请确保没有其他程序占用 build 或 dist 文件夹")
print("3. 尝试关闭杀毒软件后重试")
input("\n按 Enter 键退出...")
if __name__ == '__main__':
main()
如果要使用 nuitka打包,记得加后缀--use-nuitka
# 查看帮助
python build_optimized.py -h
# 强制使用 PyInstaller(默认)
python build_optimized.py
# 强制使用 Nuitka
python build_optimized.py --use-nuitka

浙公网安备 33010602011771号