![8e79e7221896de4e3e8fdbdc67402562.png](https://i-blog.csdnimg.cn/blog_migrate/18ae94048b81e56af024d4d448a7c1ab.png)
写在前面:
a:一般不建议将pytho程序打包,因为打包之后程序会比较大, 而且执行的效率会比较低。但事情不自己亲自动手试一试是不会体会到其中的乐(xin)趣(suan)的。
b:如果你想打包的程序包含torchvision, 且版本>=0.3.0则常规的打包方法到最后是行不通的,程序是不可运行的。可行的变通是自己将torchvision 0.2.2.post3 变为 0.3.0的版本。这个过程有些技巧性。大概的思路是:0.2版本和0.3版本以及更高版本的核心区别是少了一个C++的扩展库,所以只要弄到这个库【先安装torchvision==0.3.0 然后后进去torchvision这个包,拷贝一下里面的.pyd文件,以及一些其他的函数,然后将torchvision==0.3.0卸载, 安装torchvision==0.2.2.post3 然后将前面复制的pyd文件和一些函数复制进去,对函数层面进行适当的修改就行了】,就可以将0.2版本伪装成0.3以及以上的版本。
正文开始:
工具:>1 pyinstaller 关于pyinstaller 的介绍详见官网 http://www.pyinstaller.org
>2 虚拟环境管理工具pipenv(强推):区分开发环境和运行环境还是很有必要的,而且会使程序的体量减少。
【NOTE】 安装虚拟环境以前,首先要确保电脑中是否已经安装了python 并确认python的版本。最好不要和Anaconda共用一个python,可能打包的时候会有些bug。
Pipenv 虚拟环境安装:pip install pipenv
等待安装成功
构建虚拟环境:pipenv可以为每一个project构建一个虚拟环境,当然也可以多个project共享一个虚拟环境。
这里展示为一个单独一个项目构建虚拟环境。(多个项目共享一个虚拟环境的情况只要再包含这些项目的目录下构建虚拟环境即可)
STEP1: 使用win+R组合键打开“运行”窗口,运行“cmd”进入控制台模式。
然后在控制台中进入到你所想打包项目的目录下面【也可以先进入项目所在的文件夹,然后先按住‘shift’键,
然后点击鼠标右键,这个时候会出现“在此处打开命令行窗口”或者是“在此处打开powershell窗口”】
STEP2: 在窗口里键入pipenv --python 3.x
注:3.x表示安装的python版本,根据你已经安装在电脑中python为主。
例如,你已经安装了python3.7,
那么pipenv --python 3.7 表示构建一个虚拟环境,以python3.7 作为编译器。这个虚拟环境的位置一般在C:Users用户名.virtualenvs 中
STEP3: 环境构建完成后,通过
pipenv shell 命令进入到这个虚拟环境。要想退出这个环境,输入命令
exit 就可以退出这个环境了。为某个项目构建虚拟环境会在该项目所在目录里面生成一个
Pipfile 。这个Pipfile主要是记录了这个虚拟环境里所安装的packages。如下图所示:
![fccac4ec0080d20ed8376600adcbe179.png](https://i-blog.csdnimg.cn/blog_migrate/99040822ee9bcb06caa1766259b517a1.png)
可以在url里面更换成国内的镜像源,加快packages的下载速度。我这里用的是清华的镜像源:
后来就要为这个虚拟环境安装一些你所需要的pakages
有两种方法可以安装你所需要的包。一种是通过pipenv install name_of_packages 来安装,另一种是事先准备好你这个项目所需的所有packages,写在一个txt文件中
,如
![4586e282b54d0e3394e0fffb34b0df77.png](https://i-blog.csdnimg.cn/blog_migrate/7accabfb0a0f9bcef1063d426e665b50.png)
然后统一安装:
pipenv install -r requirements.txt
NOTE:
pipenv安装packages会生成一个Pipfile.lock的文件,这个文件主要是关于所下载的packages的一些信息。
![23cad74121cc12e4fa30923fa278ab10.png](https://i-blog.csdnimg.cn/blog_migrate/6ecfdc9426e68f5a9bf4dbdbacf45aeb.jpeg)
这里有每个包的hash值来校检包的完整性。
需要注意的是,有点时候可能会因为hash值不匹配而导致安装失败,这个时候不要慌张,其实不是你的package有问题,可能是因为官方对于package做了改动但是没来得及更新,解决办法是先通过pip list看看你所需要的packages是否安装成功(最好进入python环境中,import 一下)。如果检查没问题的话,那么可以将Pipfile.lock删除。然后在控制台中通过pipenv lock来生成新的Pipfile.lock,其实如果一直生成不了,其实也不影响pakages的使用。
SETP3:假设你们能成功到达第三步,那就恭喜你了,正式入坑了。打包的过程中会出现很多意想不到的bug。
最有意思的事莫过于debug了,不是吗?(流着泪)
<a> 首先要验证你的程序是否能正常运行
python your_program.py
测试一下所有功能是否正常后再进行打包。
<b> 如果检查程序运行没有问题,那么就要开始打包了。打包所需的工具是pyinstaller。最简单的打包操作是在控制台中输入 pyinstaller
your_program.py 。
这种情况就会生成两个目录:build和dist目录。build为临时目录,打包完成后可以删除,dist为打包完成后.exe文件所在的目录。
有两种打包模式,第一种是打包成一个目录的形式 D 即:软件在一个目录中,目录中还包含其他的文件。
第二种是打包成一个文件的形式 F 即:只打包成一个.exe文件,里面没有其他的文件。
第一种的命令为 pyinstaller -D your_program.py
也等价与
pyinstaller your_program.py 可见打包为文件夹的形式是默认的行为。说明这种行为会很常见。
第二种命令为 pyinstaller -F your_program.py
这个仅以一个.exe文件的形式表示出来,用的频率会少一些。
至于什么情况会用第一种,什么情况会用第二种,我的总结是:如果你的程序很简单,而且没有你自己写的一些pakages需要调用的话,那么请放心使用任意一种。但是如果你的程序比较复杂,那么最好是要用第一中打包模式。先将第二种情况。如果我当前的程序目录是这样的:
![3c017804a960bad5922f309730dc3f93.png](https://i-blog.csdnimg.cn/blog_migrate/cd84c6cace9b97e198fe143af038d33a.png)
即这里面的五个程序都是同级的,main.py作为主函数,分别点用了前面四个.py 文件中的内容。那么这个时候可以直接使用
pyinstaller -Fw main.py 进行打包【w参数是表征是不显示控制台】这样的话如果打包的过程中没有出错的话,就可以愉快的使用了,就算是程序报错了,也会有弹窗提醒。
如果你的程序里面有些其他的资源,如图标、动画、图片数据。假设是这样存放的:
![94a1d7b981557fcd0087711b94882f9a.png](https://i-blog.csdnimg.cn/blog_migrate/212626ebb03c2616fa60a3311335bafc.png)
那么打完包之后不要忘了将datas里面的数据拷贝到dist/main目录里面去(因为main.py 和 datas在原始目录中是平级的关系,所以在生成后的目录中也要保持平级的关系)
。
下面着重将第一种。
如果你的目录是这样安排的:
![fa356290b7400fb51ff31c9243b3706b.png](https://i-blog.csdnimg.cn/blog_migrate/bb027803951a23c3b5553951f6cb7347.png)
这里面的关系是lib目录和datas目录和main.py
同级。而main.py 则需要调用lib和datas里面的函数和资源文件。
那么这种情况下,最好是用-D的模式打包,即pyinstaller -Dw main.py
那么打包成功之后,记得将lib目录和datas目录下的文件都要拷贝到dist/main目录下面。
STEP4[Optional]: 这一步不一定会需要,但是一般如果需要更高级别的操作和灵活性,那么这一步是你的首选。我们无论是使用D模式还是F模式,都会在当前目录下生成一个【假设主程序叫做main.py】。
![7557f3c556ab3c33ca2a3e0d21b1489f.png](https://i-blog.csdnimg.cn/blog_migrate/2ee8d7fddc2bd8cbdb29d3ec3cb8400f.jpeg)
这个文件里面分为几个部分,第一个部分是Analysis,顾名思义是分析的部分,分析需要打包的文件,需要导入的数据[datas]、动态库[binaries]、隐藏的库[hiddenimports]等等。第二部分是PYZ部分,不需要特别关注。第三部分是EXE部分,里面有关于生成的可执行文件的一些性质。如名称[name]、是否开启debug模式[debug, 调试阶段建议把这个设置为True,
可以看到bug出在什么地方],
是否使用upx压缩[upx]等等。最后一个COLLECT部分就是将前面的三个部分收集起来。
灵活使用.spec文件会避免出现很多bug哟。
我一般打包程序都是分两步,第一步生成main.spec文件,然后在pyinstaller main.spec [注意:此时pyinstaller后面接的是.spec文件,而不是.py文件]
具体来说:使用pyi-makespec -D main.py
来生成main.spec 此时还未开始打包。
然后打开main.spec文件,在Analysis部分田间程序所需的datas,binaries, hiddenimports。需要注意datas的格式为[('original/path/to/data1', 'to'), ('original/path/to/data1', 'to')] 表示的意思是系统将自动把原本在 original/path/to中的data1,
拷贝到dist/main中的to文件夹中。
Binaries 也是一样的格式(一般一开始不知道缺了什么动态库,即DLL文件,一般先运行一次pyinsatller main.spec
过程中有一个“Looking for dynami libraries”,如果缺了什么库,就在前面提到的虚拟环境里查找这个DLL文件,然后复制这个DLL文件到项目所在的目录下)
,hiddenimports值的是你原本已经安装,但是再程序的运行中未找到的pakages
。
STEP5[Optional]
: 这一步是关于压缩程序的,有的时候即便是在虚拟环境中进行打包,最后程序还是很大。这个时候如果想进一步压缩程序,则可以使用upx选项。
关于upx的介绍:https://upx.github.io upx是一款免费、小巧的对exe文件进行压缩的软件。在官网上下载自己pc所对应的版本,直接解压就行了。(解压后还不能直接使用,需要配合pyinstaller 一起使用)
正确的使用方法:
pyinstaller --upx-dir path/to/upx --clean main.py
--clean 参数是清楚一些残留的,--upx-dir 指的是刚刚你下载解压所存放upx的目录。
Note:使用UPX经行压缩时,可能程序是变小了一些,但是程序也不能用了。排查这种错误一般比较复杂,建议先以不压缩的模式得到一个可以正常使用的程序,将这个程序保留,然后看使用upx压缩后的程序的报错,定位到某个dll文件【一般是因为upx将某个启动的dll文件压缩了,导致程序无法正常启动】,这个时候将无压缩的程序中的dll文件拷贝到使用upx压缩的文件夹中即可。
------------------------------------END 2019.9.22[modified 1]--------------------------