最近打算把自己写的程序用pyinstaller做一个打包,以便在其他电脑上使用,本来以为挺简单的事情,没想到搞了两天时间才搞定,期间遇到诸多坑,忍不住要骂娘了。
平心而论,搞不定只能是自己学艺不精,所以只能调整好心情,挨个去排除异常,面向csdn编程。
提醒:
如果你打包的程序是单文件,并且不依赖于第三方库、第三方软件,那就没必要看本文。网上大把的教程,一行命令就成功打包了。
如果你的项目文件写的比较正规、多目录、并且还依赖了第三方的软件或文件等等,那本篇文章是比较有参考价值的。
我的项目目录如上图。
ok,进入正题。
需要说明的是,每个人的python解释器版本不同,甚至用到的pyinstaller版本不同,都会产生各种问题。
总体思路:
项目完毕后,在自己的pycharm里先运行,看是否报错,报什么错。将报错信息复制到别的文档中去,方便挨个排查。
报错信息通常都包含关键词:error、warning。
所以,你只需要在你刚才粘贴过去的文档 ctrl+f,然后查找错误信息即可。
有英文基础的话,就很清楚的知道,它说的是upx不可用。
因为pyinstaller打包会用到压缩功能,而这个功能依赖于UPX,UPX是一款压缩软件,所以,你应该下载UPX的安装包,然后把upx.exe文件放在项目虚拟环境中的Scripts文件夹下。
具体操作方法看这篇参考文章:
pyinstaller打包时提示UPX is not available._Veiko的博客-CSDN博客
第一种:TypeError: an integer is required
第二种:win32*******.error 。比如文件找不到,外部卷被破坏之类各种win32错误。
如果你遇到这两种错误,先卸载你的pyinstaller。重新用下面的命令安装
pip install https://github.com/pyinstaller/pyinstaller/archive/develop.tar.gz
我使用这个办法,成功解决了上面两种错误。
参考文章:
python用pyinstaller生成exe时报错 TypeError: an integer is required (got type bytes)_TLScott的博客-CSDN博客
ok,上面是常见错误,一般刚开始用pyinstaller都很容易遇到,下面再说一些我遇到的其他错误
凡是你用到moviepy库,总是会遇到各种奇葩报错。
背后真正的原因是,我们使用的第三方库在运行时,也会导入其他第三方的库。专业名词叫隐藏导入。
大多数模块的开发者都会根据python版本的变化,及时更新正确的语法和用法。
但是moviepy的开发者就偷懒了,使用了一种偷懒的方法去导入第三方库。
所以,我们在用的时候,会报各种乱七八糟的错。
解决办法是,修改下面两个文件的内容。
注意,是all文件夹下面的--init--.py,别修改错了。
打开后页面如下:
我们这里修改的是moviepy.audio.fx.all.__init__.py, 另外一个moviepy.video.fx.all.__init__.py也做同样操作。
注意,不要修改错了,是all文件夹下面的__init__,不是它的同级目录的init。
另外:网上别人给出的代码不要直接复制过去,一定要像我上面演示的一样,手动打印结果,再复制修改。
因为每个人的moviepy版本可能都不一样,你复制别人的代码,到时候还是可能会报错!
参考文章:
moviepy应用pyinstaller打包后执行报错AttributeError: module audio/video.fx.all has no attribute fadein、crop_LaoYuanPython的博客-CSDN博客c
自己在pycharm里运行,完全没问题,直接在打包后的目录里运行也没问题。
换个目录运行或者换个电脑,就报错。
老手一看,哎,这不就是相对路径没用好么,把项目里的绝对路径改为相对路径。这样换目录、换电脑运行不就可以了?
思路完全正确,不过可能依旧解决不了问题!
我就遇到了,死活搞不定,明明打包后的文件夹里就有配置文件,就是获取不到文件路径。
最后使用了‘冻结路径’的方法配置资源文件路径,程序成功运行。
简单的说,就是在自己项目的根目录中再创建一个py文件,里面定义两个函数,来做一些判断。
这样,程序会根据不同的运行回来,来取不同的值
自己的哪个模块需要使用资源文件,就在对应的py文件中导入这个自定义的模块frozen.py,然后来获取路径的值。
表达的有点绕口,截图展示一下。
比如我的业务代码都在src文件中,需要用到这些资源文件的地方,就用上面我们自定义的模块的函数来取值即可。
至此:程序已经成功运行,在别的电脑也没问题。
参考文章:Python项目打包后找不到路径问题,将资源文件数据文件打包到exe文件中_马克图布s的博客-CSDN博客_python打包路径问题
打包多文件夹、并且还要依赖其他的一些字体文件、音视频文件、甚至第三方软件、亦或者一些dl文件,都需要在spec里配置。
配置好了之后直接 pyinstaller xxx.spec即可。
这是必须要学会的技巧。
spec文件可以使用命令 pyi-makespec xxx.py 即可生成,其中xxx是你的项目入口文件
生成之后,我们主要需要配置的就是这4个地方,其他的无伤大雅。
咱主要说一下这个datas参数
可以看到datas是一个列表,列表的元素只能是元组,元组第一个元素是你想要打包的文件或者文件夹路径,右边是打包后的程序目录路径。
这些配置完毕之后,运行pyinstaller xxx.spec即可,打包后的程序在dist目录下。
还有一个问题:
使用.cfg文件配置文件路径有一个坑,这里说明一下。
cfg文件里的路径,不要加引号,直接写上去就可以了。
如果加了引号,会导致configparser模块获取到的路径和你配置的不同,会引起一些不必要的错误。
比如,我就遇到了,很抓狂....
抓耳挠腮半小时,灵光一闪,是不是配置文件的路径不需要引号呢,修改一下就正常了.....