pyinstaller打包一个Pytorch项目及其常见问题

张开发
2026/4/10 20:06:12 15 分钟阅读

分享文章

pyinstaller打包一个Pytorch项目及其常见问题
文章目录1、如何打包2、常见问题2.1 闪退2.2 OSError: could not get source code2.3 ModuleNotFoundError: No module named unittest.mock2.4 Aborting build process due to attempt to collect multiple Qt bindings packages: attempting to run hook for PyQt5, while hook for PySide6 has already been run! PyInstaller does not support multiple Qt bindings packages in a frozen application - either ensure that the build environment has only one Qt bindings package installed, or exclude the extraneous bindings packages via the module exclusion mechanism (--exclude command-line option, or excludes list in the spec file).2.5 文件读写失败可缺失一些资源文件2.6 Failed to load cpm_kernels:File cuda/embedding.fatbin not found in cpm_kernels.kernels.base2.7 图标不更新2.8 双击后无任何反应在终端执行也无任何反应和报错信息xx 其他异常3、打包CUDA环境我有一个基于pytorch的动漫化Stable Diffusion项目使用pyside6写了一个可视化界面。但是在新环境使用需要搭建Nvidia-Driver、CUDA、cuDNN和含pytorch的python环境十分繁琐所以需求是将项目打包为可执行文件打包过程中将python环境一起打包在新环境可以使用自带的python解释器所以不需要配置python环境。pyinstaller是python项目的一个打包工具也有可视化的auto-py-to-exe工具实际上就是pyinstaller非官方的gui版本在需要打包的环境中安装pip install pyinstaller即可1、如何打包pyinstaller本身是命令行工具比如主程序为main.py通过pyinstaller main.py就会打包为exe文件Windows或可执行文件Linux一些常用的参数如下-F, --onefile将所有文件打包为一个单独的可执行文件更干净但在运行时会将打包内容解压到临时目录中会影响启动速度。-D, --onedir将所有文件打包为一个目录包含可执行文件和所有依赖的文件默认这种方式通常更方便调试因为所有依赖都放在一个目录下更容易找到和替换特定的文件。实际上在打包分为两个过程生成.spec文件前和生成.spec文件后。.spec描述了如何将应用程序和所有相关的依赖项打包在一起第一阶段会分析代码记录依赖的库等信息生成.spec文件。生成后这个文件是可以手动修改的实际上和pyinstaller的参数是一样的可以在命令行指定也可以在.spec修改。如果已经有一个.spec文件也可以通过pyinstaller main.spec根据你制定的spec文件进行打包更加可控。通过pyinstaller main.py或者pyinstaller main.spec成功打包一个exe文件但是你激动双击后会发现诸多Error2、常见问题依赖问题是最常见的问题这里重点讲一讲依赖。pyinstaller会生成spec文件该文件中记录可pyinstaller自动扫描的依赖文件。pyinstaller扫描分析阶段通过扫描import关键词构建依赖图并将所有依赖打包到exe启动时动态加载。但是可能存在两个问题1pyinstaller没有检测到import导致某些import依赖没有被记录2文件不是python模块不会被扫描比如图片、ui、文件等等资源。模块未检测且未导入为什么会检测不到1pyinstaller是静态分析但是python支持动态导入。你的项目如果使用了module __import__(xxx); importlib.import_module(xxx)类似这种通过字符串导入就无法被扫描到。2插件机制。如果使用了类似load_plugin(core.file_renamer)的插件机制只有在运行时才会确定也无法被pyinstaller的静态分析扫描到。3导入混乱pyinstaller没有识别到模块的完成路径解决办法1如果是自己写的模块没有被打包则通过hiddenimports参数指定模块:hiddenimports[renametool.core.file_finder,]2如果是第三方库则直接hiddenimports[cv2,numpy]。或者如果不确定缺少什么直接添加debug参数pyinstaller main.py --debugimports在日志中会打印ModuleNotFoundError。或者正常打包执行后提示哪个依赖找不到再手动添加到hiddenimports中文件未导入spec中datas是解决文件未导入的问题通过datas[(src, dst)]方式告诉pyinstaller这些是必须的文件。通过这种方式将pyinstaller不会自动包含的json、yaml、ui、jpg、pt、onnx、txt等文件都一起打包比如(os.path.join(current_dir, ImageCropTool, config.json), ImageCropTool),将指定路径中的config.json打包打包后路径为/ImageCropTool/config.json。一个潜在的问题出现了文件的路径是相对路径。在代码中使用必须使用代码获取当前文件夹路径进行拼接如果将路径写死打包后也会因为路径不正确报错找不到importsysimportosifgetattr(sys,frozen,False):base_pathsys._MEIPASSelse:base_pathos.path.dirname(__file__)config_pathos.path.join(base_path,ImageCropTool,config.json)2.1 闪退双击软件后窗口闪退一般都是程序出错也算是程序运行结束自动关闭。可以先打开一个cmd窗口然后手动.\main.exe执行这样程序结束后就不会闪退可以看到具体的报错问题。或者在打包之前使用异常捕获比如在主程序main.py中if__name____main__:print(程序正在启动中......)try:# 你的核心程序run()exceptExceptionasex:print(f程序出错:{ex})input(按下任意键退出...)当打包后双击exe出错也会被程序捕获不会闪退2.2 OSError: could not get source code这个问题和pytorch有关当你定位到问题函数会发现被torch.jit.script装饰网上多数也是由于这个装饰引起的。解决办法时在主程序的最开始加入下面代码defscript_method(fn,_rcbNone):returnfndefscript(obj,optimizeTrue,_frames_up0,_rcbNone):returnobjimporttorch.jit torch.jit.script_methodscript_method torch.jit.scriptscript2.3 ModuleNotFoundError: No module named ‘unittest.mock’spec文件中设置hiddenimports[unittest.mock],该类型的错误都可以手动添加到依赖hiddenimports。对应的命令行参数是--hidden-import还遇到ModuleNotFoundError: No module named cupy_backends.cuda._softlink直接到库文件夹下定位到cupy_backends.cuda发现存在一个_softlink.cp310-win_amd64.pyd将其复制。再比如ImportError: cannot import name _util根据报错可以定位是cupy库的问题通过对比发现仍然是缺少该问题。实际上很多库并不是完全打包了因为引用问题只打包了部分库中的文件。2.4 Aborting build process due to attempt to collect multiple Qt bindings packages: attempting to run hook for ‘PyQt5’, while hook for ‘PySide6’ has already been run! PyInstaller does not support multiple Qt bindings packages in a frozen application - either ensure that the build environment has only one Qt bindings package installed, or exclude the extraneous bindings packages via the module exclusion mechanism (–exclude command-line option, or excludes list in the spec file).似乎是pyside6和其他QT冲突解决办法参见 https://blog.csdn.net/2301_79954314/article/details/140937024没有安装pyqt的可以pip list查看有哪些pyqt包然后卸载。2.5 文件读写失败可缺失一些资源文件将缺失的资源文件复制到指定文件夹2.6 Failed to load cpm_kernels:File cuda/embedding.fatbin not found in cpm_kernels.kernels.base上面是针对cpm_kernels库类似这种报错首先查看库打包后的依赖目录是否有这个库没有则复制进入即可2.7 图标不更新在spec文件中通过iconadhmy-tlihr-001.ico,指定图标图标文件需要在同级目录打包后产生的exe文件仍然是默认的。首先注意到启动后有图标。根据文章python3 pyinstaller 图标改变不了的问题提到资源管理器缓存问题尝试将main.exe复制到其他文件夹确实有图标了放回去又没有应该就是缓存问题。此时可以重启电脑或者重启资源管理器在任务管理器的详细信息页卡中结束explorer.exe然后文件-运行新任务-浏览在C:\Windows中找到explorer.exe启动即可。2.8 双击后无任何反应在终端执行也无任何反应和报错信息我遇到的这个问题将源_Intelnal文件夹复制到该项目并替换就好了可能是对_internal中某些文件误操作导致缺少某个文件xx 其他异常需要定位点打印信息如果是一个文件路径需要检查是否存在否则复制源码到该路径下。3、打包CUDA环境上述虽然可以不用配置python环境但是还是需要安装GPU驱动和CUDA。当你打包得到exe和_internal文件夹后可以直接去CUDA的安装文件夹C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\bin复制所有文件到_internal文件夹下。但是可以发现其中有很多的dll文件有一些可能和项目无关我自己的项目经过测试下面这些是用不到的去除分隔符还是可以正常运行总共约1.8GB。除此之外一些exe文件也是没用的虽然文件比较小也可以排除减小发行包的大小。事实上上面的dll库在_internal\torch\lib也有所以是重复了。_internal\torch\lib文件夹约4G文件如下

更多文章