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


    1 opencv兼容性问题

    1.1 现象

    打包为一个exe完成后,在执行exe时,报错:
    ImportError: ERROR: recursion is detected during loading of “cv2” binary extensions. Check OpenCV installation.
    如下图所示:
    在这里插入图片描述

    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。如下图所示。
    在这里插入图片描述
    在这里插入图片描述

    2.2 原因及解决方式

    yolov5中应该是用到这两个,但是没包含。
    (1)general.pyc为二进制文件,为general.py编译后的格式,在VSCode中,运行工程文件,python中运行general.py时,自动生成了这个pyc文件,这个文件位于文件夹下面。
    在这里插入图片描述
    在这里插入图片描述
    但这里生成的是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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    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。
    这个在命令行运行时,提示倒没什么。因为我做了一个界面程序,每次启动时,有弹窗提示,如下图所示,让人很不爽。

    在这里插入图片描述

    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    补充说明: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 )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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 )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

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

  • 相关阅读:
    vue大型电商项目尚品汇(前台篇)day05终结篇
    手摸手带你 在Windows系统中安装Istio
    Linux该如何学习,给你支招
    python_pdf常规使用
    web分析-手把手教你怎么写小程序事件分析
    能链科技获评中国最具投资价值企业榜单TOP10
    vue-element-admin用户登录流程(上)
    Android 12 intent-filter添加android:exported后任然报错解决方法
    模拟ASP.NET Core MVC设计与实现
    深入探讨 Golang 中的追加操作
  • 原文地址:https://blog.csdn.net/kevinshift/article/details/125475122