树莓派中使用pyinstaller打包多个.py文件为exe可执行文件报错

写在前面:本人对linux系统操作不熟悉,由于项目需求,需要对树莓派上的多个.py文件进行打包,最终形成一个EXE可执行文件。过程非常曲折,历经九九八十一难可谓是打包成功了,走了很多弯路,Linux系统也确实有很多需要注意和踩坑的点,现把我的解决方法整理记录一下,以便后续遇到同样的问题,希望也能帮助到和那些我一样绝望的uu们。

本机Linux系统打包基本配置

  • Linux系统内核版本号:Linux raspberrypi 5.15.84-v7l (v7l表示32位)
  • 编译器版本信息:Raspbian 10.2.1
  • python使用版本:python 3.9.2
  • pyinstaller使用的版本:pyinstaller 5.5
    • 不清楚如何查询版本号的参考:查看树莓派系统及版本
    • 查询python版本:python --version
    • 查询pyinstaller版本同理,也可以在终端使用:pyinstaller -v
      演示:
      在这里插入图片描述
      这里要注意的一点:下载的pyinstaller版本需要支持你的python版本,否则打包不成功。官网(pyinstaller.org)最新的pyinstaller是5.8.0,但是它只支持python3.7及以上的打包,如果你的python版本过低,就会打包不成功。

使用pyinstaller打包成exe

阶段一:完成打包操作

可以使用python定位到pyinstaller打包也可以直接pyinstaller打包,我试过都可以打包成功。

方法一:
1.先定位到pyinstaller(我解压放在了桌面上)文件夹中的bootloader文件夹上,因为这里面有waf文件,方便后续打包失败彻底清除。

prototype2@raspberrypi:~s cd /home/prototype2/Desktop/pyinstaller/bootloader  

这里我是直接cd 然后右击bootloader文件夹复制其路径粘上去,这样更方便
2.这里就可以开始打包了

prototype2@raspberrypi:~/Desktop/pyinstaller/bootloader s pyinstaller -F /home/prototype2/Desktop/version_0.0.4/breath_python/websocket_connect.py

这是直接使用pyinstaller打包,语法:pyinstaller -F main.py(主程序运行的绝对路径)

这就打包成功了,由于我们是在bootloader文件夹下打包的,所以最后会在该文件夹中生成两个文件夹,分别是dist和build文件夹,打开dist文件夹里面就生成了一个exe文件,如果到这里打开,你的程序就可以正常运行了,那么恭喜你,如果没有,请继续看下去。

方法二:
1.第一步同样定位到pyinstaller(我解压放在了桌面上)文件夹中的bootloader文件夹上。

prototype2@raspberrypi:~s cd /home/prototype2/Desktop/pyinstaller/bootloader

2.打包命令:

prototype2@raspberrypi:~/Desktop/pyinstaller/bootloader s python /home/prototype2/Desktop/pyinstaller/PyInstaller -F /home/prototype2/Desktop/version_0.0.4/breath_python/websocket_connect.py

这是python调用pyinstaller包进行打包,语法:python PyInstaller的绝对路径 -F main.py的绝对路径

这里PyInstaller(和bootloader在同一个目录下)是在我解压的pyinstaller文件夹中,我把这个文件夹放在了桌面上,所以它的路径如上述。

到这里,打包完成了,这个环节有几点要特别注意:

  • 多个.py文件有一个主程序文件(我这里是websocket_connect.py),该主程序文件调用了很多其他.py文件,那么文件放置的位置一定要和程序里调用的.py文件路径一致,如果直接调用某个.py文件,那么主程序文件一定是和这个文件在同一个目录下,否则路径会错误找不到。
  • 如果你在打包时告诉你权限不够,那就在程序的第一步提前加上sudo -s 就可以了。
  • 如果最终打包终端显示已经成功了,但是dist文件里面什么都没有,试试sudo reboot重启树莓派,它卡了,我出现过好几次这样的情况。
  • 前提没有打包之前程序是可以正常运行的,否则打包后也无法成功。

阶段二 点击打包后的exe文件无法打开解决方法

故事从这里才真正开始,打包后遇到的第一个问题就是,打开dist文件后点击exe,程序无法执行,得到终端报错信息:
Couldn’t open res/image/background.png

Couldn't open res/image/background.png

其实,这个问题挺简单的,是路径问题,只不过我当时不清楚花了很长时间去解决,还把代码中的相对路径改成绝对路径等等,不推荐这样,尤其使用的资源特别多的时候。

如果生成的exe文件打开报错:Couldn’t open xxxx ,很大可能就是没有把需要的图片、音频等资源放在生成的exe同目录下,导致其无法打开该资源,这里还是要注意要与程序中调用路径相同。

解决:把res这个文件夹和其他主程序下要用到的资源一起拷贝到exe同目录下,相当于阶段一所说的第一点注意点。

补充:如果文件复制到exe所在的dist文件夹权限不够,可以使用命令cp复制,也可以直接修改该文件夹的权限sudo chmod 777 /home/prototype2/Desktop/pyinstaller/bootloader/dist 即sudo chmod 777 dist的绝对路径,这样就可以粘过去了。

至此,点击exe文件就可以打开界面了,其他功能都能正常运行,但是,pygame模块,一点击游戏开始终端闪退,页面显示连接不上。

阶段三 点击打包后的exe文件运行pygame游戏模块闪退解决方案

游戏一点击程序就闪退,几毫秒的事情,终端也退出了,页面也无法再次连接,通过录屏截取了程序报错信息:
Fatal Python error: pygame_parachute:(pygame_parachute) Segmentation Fault
Python runtime state: initialized
Traceback (most recent call last):
File “pygame/pkgdata.py”,line 67,in getResource
FileNotFoundError:[Errno 2] No such file or directory:‘/tmp/_MEIHEonzn/pygame/freesansbold.ttf’

Fatal Python error: pygame_parachute:(pygame_parachute) Segmentation Fault
Python runtime state: initialized
Traceback (most recent call last):
File "pygame/pkgdata.py",line 67,in getResource
FileNotFoundError:[Errno 2] No such file or directory:‘/tmp/_MEIHEonzn/pygame/freesansbold.ttf'

这一part走了很多弯路,尝试很多方法,试过搜索tmp文件夹和全盘搜索该.ttf文件,创建复制该文件夹,.ttf会出现感叹号不可用,也试过修改font(None,xx)为font(‘Arial’,xx)等等,依旧同样的问题,大致原因是pyinstaller有些资源是默认不打包进去的,所以就出现了不完整,找不到等情况。

解决方案:手动打包添加缺失文件 --add-binary<Src:Dest或者Src;Dest>

参数解释:

  • Src打包缺失的文件在本机的位置
    [ 最好使用绝对路径,我是在全机搜索的该文件,因为用的python3(之前和python3.9进行了软链接),所以使用的是…(安装python的位置,根据情况而定)/python3/dist-packages/pygame/freesansbold.ttf ]

  • Dest: 文件运行时,需要动态拷贝到的相对目录
    [ 如这里提示的是/tmp/_MEIHEonzn/pygame/freesansbold.ttf,其中/tmp/_MEIHEonzn/是每次打包执行的绝对路径开始的地方,_MEIHEonzn每次打包都会自动随机生成一个,所以Dest在这里只需要输入相对路径;对于上述,Dest应为pygame ]

  • Linux系统分隔符用的是:

  • Windows系统分隔符用的是;

所以,本机添加的代码为`–add-binary=“/usr/lib/python3/dist-packages/pygame/freesansbold.ttf:pygame”

添加该参数代码目的:把本机的 freesansbold.ttf 文件打包到执行文件中,并且运行时动态释放到 相对目录 pygame 中,从而解决 错误提示 的文件找不到问题

更详细的说明参考python3 pyinstaller 打包后执行文件运行错误 No such file or directory 和 Cannot load native module 解决方法

接下来我就使用以下代码完成打包:
1.定位到bootloader文件夹

prototype2@raspberrypi:~s cd /home/prototype2/Desktop/pyinstaller/bootloader

2.进行打包并添加缺失文件

prototype2@raspberrypi:~/Desktop/pyinstaller/bootloader s pyinstaller -F /home/prototype2/Desktop/version_0.0.4/breath_python/websocket_connect.py --add-bianry"/usr/lib/python3/dist-packages/pygame/freesansbold.ttf:pygame"

到此,打开dist文件,别忘了把其他资源文件拷过来(阶段二),然后打开exe文件,程序其他模块正常,点击游戏模块也不闪退了,主程序也不关闭了,但是游戏窗口是黑屏,只有一个头部名称,吹数据在终端都有显示,就是游戏模块无法显示!!!
这过程非常曲折,每当我准备放弃的时候,又出来一线生机,让我忍不住跟下去。

阶段四 打包后pygame游戏界面无法显示解决方法

目前其他模块正常,游戏界面无显示,终端也能出数据,于是截取了报错信息:
在这里插入图片描述
TvpeError:expected str. bytes or os.PathLike obiect, not BytesIo
大致问题还是上述字体问题并没有彻底解决,系统找不到相应字体,这里直接附上我的解决方法:

思路:pygame游戏模块写的代码中用到了pygame .font .SysFont (None, xx)全部替换掉系统目前已经有的字体,这样就不会出现找不到的情况了。

  1. 查看树莓派系统中已有字体命令:fc-list
    截取了一部分:
    在这里插入图片描述
    由于我需要的是中文显示界面字体,所以使用fc-list :lang=zh查看系统中安装的中文字体,中文字体需要自己下载,我之前下载过
    在这里插入图片描述
    从中随便选择一个字体,比如
    在这里插入图片描述
    前面/usr/…/wqy/是/wqy-zenhei.ttc的文件存储路径,可以从这个路径里找到需要字体.ttc/.ttf文件,后面从.ttc冒号后面到style冒号前面整个部分:文泉…,WenQuanYi Zen Hei是字体名称

2.将程序报错中的文件修改代码,替换None
在这里插入图片描述
修改哪些程序在报错信息里,按照上面的报错信息,我修改的是source/game.py和source/widgets.py和source/button.py因为这几个地方都用到了font,找到对应位置将None替换成你需要的字体名称即可。

到这步,程序就正常运行了,各模块运行正常,打包完成,不过唯一一点,英文按钮并没有转换为中文,因为虽然换了字体,代码中名称设置依旧为英文的,我又将页面显示的英文字如“Restart”“Exit”(这些都是在pygme自定义的名称)在程序中全手动修改成中文,最后显示出来才会是中文,部分代码修改如上图。

  • 在widgets.py文件中将原来使用的字体文件路径替换成现在使用的字体路径,在上述字体路径找到复制到目前字体的目录上就可以使用相对路径,复制无权限上面有介绍,chmod 777 … ,也可以直接使用绝对路径,修改如下,不过这步不换也不影响的:
    在这里插入图片描述
如果出现第三阶段找不到.ttf文件的问题时,可以直接用第四阶段的方法一定是可以的,后来又尝试不加–add-binary=“…:…”,直接修改None为系统字体,需要显示的改为中文命名,打包成功,所以完成第四阶段设置最后可直接用该命令打包:pyinstaller -F /home/.../main.py

在这里插入图片描述

补充:

每次打包失败,需要重新打包时,需要把生成的dist和build文件删除,同上也是定位到bootloader文件夹,并用里面的waf文件清理打包文件

rm -rf dist
rm -rf build
python ./waf distclean all

每次重新打包前都要操作一下
至此,打包工作结束!!!

如果有任何问题,欢迎大家交流指正,希望给打包的uu们提供一些帮助,upupup!!!

其他参考链接:https://www.cnblogs.com/aby321/p/13628330.html
https://blog.csdn.net/yuxingdeyun/article/details/120013000
https://github.com/pyinstaller/pyinstaller/tree/develop/PyInstaller

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值