[python]使用pyinstaller打包带界面的Pytorch程序的多个问题

1 opencv兼容性问题

1.1 现象

打包为一个exe完成后,在执行exe时,报错:
ImportError: ERROR: recursion is detected during loading of “cv2” binary extensions. Check OpenCV installation.
如下图所示:
[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第1张图片

1.2 原因及解决方式

pyinstaller和cv2版本存在兼容问题,卸载已有的opencv-python,安装opencv-python=4.5.3.56

本人安装的为python3.7,pyinstaller5.1,opencv版本高了.

可参见这里:https://blog.csdn.net/weixin_50850903/article/details/125231985

2 缺乏yolov5下的两个文件general.pyc和coco128.yaml

2.1 现象

打包为一个exe完成后,在执行exe时,报错:缺少general.pyc和coco128.yaml。如下图所示。
[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第2张图片
[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第3张图片

2.2 原因及解决方式

yolov5中应该是用到这两个,但是没包含。
(1)general.pyc为二进制文件,为general.py编译后的格式,在VSCode中,运行工程文件,python中运行general.py时,自动生成了这个pyc文件,这个文件位于文件夹下面。
[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第4张图片
[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第5张图片
但这里生成的是general.cpython-37.pyc,不是general.pyc,这也可能是找不到的原因。
将其进行重命名为general.pyc即可。
然后把他放在了utils下面。
(2)coco128.yaml为文本格式文件。工程中就有,在data\下面。直接用即可。

解决方法,在spec中包含这两个文件即可。
spec定义如下:

a = Analysis(['D:XXX\\detect.py'],
             pathex=[],
             binaries=[(r'D:\XXX\XX\utils\general.pyc', r'.\utils' ) #进行拷贝,注意拷贝的目的文件夹需要与上面缺少的路径一致。
				],
             datas=[(r'D:\XXX\data\coco128.yaml', r'.\data' )],		#进行拷贝,注意拷贝的目的文件夹需要与上面缺少的路径一致。
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)

3 缺乏yolov5下的两个文件general.pyc和coco128.yaml

3.1 现象

运行exe时,可以运行,但是有报警:
WARNING: file already exists but should not: C:\Users\workAI\AppData\Local\Temp_MEI132522\torch_C.cp37-win_amd64.pyd。
这个在命令行运行时,提示倒没什么。因为我做了一个界面程序,每次启动时,有弹窗提示,如下图所示,让人很不爽。

[python]使用pyinstaller打包带界面的Pytorch程序的多个问题_第6张图片

3.2 原因及解决方法

不知道是不是pytorch本身的问题。这是说,在文本文件中多了一个文件,本来不应该有的,但是有了。
解决方法:在spec文件中,加一个搜索,从二进制引用的文件中,去掉这个。如下:

a = Analysis(['D:\XXX\detect.py'],
             pathex=[],
             binaries=[(r'D:XXX\utils\general.pyc', r'.\utils' )
				],
             datas=[(r'D:\XXX\data\coco128.yaml', r'.\data' )],
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
for d in a.datas:					#这样遍历一遍,删除本不应该包含的即可。spec文件其实就是可以执行的python代码
	if '_C.cp37-win_amd64.pyd' in d[0]:
		a.datas.remove(d)
		break

补充说明:spec文件其实就是可以执行的python代码!!!

4 带界面的python程序如何去掉命令行界面

4.1 现象

点击打包的exe时,先出现命令行界面,且一直有,然后再有界面。此时有个这很让人感觉不爽。

4.2 解决方法

在spec文件中,配置如下,即可不弹出命令行界面了:

exe = EXE(pyz,
          a.scripts,
          a.binaries,
          a.zipfiles,
          a.datas,  
          [],
          name='XXX',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=".",
          console=False,					#此定义为False,则不弹出命令窗口了
          disable_windowed_traceback=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None )

5 带界面的python程序启动界面

5.1 现象

打包exe程序,这个pytorch的框架中,把其相关的包都打包进去了,有3.9个G大小,启动exe,解压缩到界面弹出来,时间非常长,又没有了命令行提示,用户都不知道情况。
为此,pyinstaller有闪屏功能,就是先加载一个提示窗口,可以显示进度。
ps:这个界面也是用tinker库实现的。
方法,在spec文件中增加splash对象,进行定义即可:

a = Analysis(['D:\CNG_Work\LostDistrictIdentify\\detect.py'],
             pathex=[],
             binaries=[(r'D:\CNG_Work\LostDistrictIdentify\utils\general.pyc', r'.\utils' )
				],
             datas=[(r'D:\CNG_Work\LostDistrictIdentify\data\coco128.yaml', r'.\data' )],
             hiddenimports=[],
             hookspath=[],
             hooksconfig={},
             runtime_hooks=[],
             excludes=[],
             win_no_prefer_redirects=False,
             win_private_assemblies=False,
             cipher=block_cipher,
             noarchive=False)
for d in a.datas:
	if '_C.cp37-win_amd64.pyd' in d[0]:
		a.datas.remove(d)
		break

pyz = PYZ(a.pure, a.zipped_data,
             cipher=block_cipher)

splash = Splash(r'D:XXXX\Assets\CompanyLogo.gif',	#只支持PNG格式。其他格式的话,如果装了PIL则会自动转换
									#如果设置了最大尺寸max_img_size,且装了PIL,则尺寸大时,则自动进行转换缩放
                binaries=a.binaries,	#这里的a就是前面定义的,这里指向了他的二进制文件,
                datas=a.datas 
                text_pos= (1240,405) 			#文本提示,提示上面的加载的二进制文件名称	#None不显示,或者显示的位置(10, 50),
	      		text_default = 'Initializing'			#默认提示
                text_size=12,					#字体大小
                text_color='black'

exe = EXE(pyz,
          a.scripts,
		  splash,                   # <-- both, splash target,引用splash对象
          splash.binaries,          # <-- and splash binaries,显示加载的文件内容
          a.binaries,
          a.zipfiles,
          a.datas,  
          [],
          name='XXX',
          debug=False,
          bootloader_ignore_signals=False,
          strip=False,
          upx=True,
          upx_exclude=[],
          runtime_tmpdir=".",
          console=False,
          disable_windowed_traceback=False,
          target_arch=None,
          codesign_identity=None,
          entitlements_file=None )

更多关于splash介绍,可参见pyinstaller官方介绍。https://pyinstaller.org/en/stable/usage.html?highlight=Splash#splash-screen-experimental
里面有多个章节,可以搜索下,都看看。

你可能感兴趣的:(python,python,pytorch,opencv,界面程序)