最近有一门课的小组任务要求完成 AES 加密算法,语言不限,并且提交一个完整的工程和测试程序,还要附上 README。因为对我来说难度稍微低一些,我就直接把这个给做完了。(微笑)
为了锻炼一下我的 Java 水平和能力,所以我一开始打算全部用 Java 来写,但后来因为偷懒不想写为了展现我们灵活而全面的技术栈,所以我就用 Python 写了一个文件对比的脚本。
pyinstaller 的安装
考虑到 Windows 各种各样的使用环境,我们直接发一个 .py 的脚本是不一定能够在其他电脑上正常运行的。因此为了方便就必须要给程序做打包,把 Python 的环境全部打包到一个二进制文件里面,这样就能够做到独立运行了。
pyinstaller 是一个专门用来做 Python 脚本打包的库,如果没有可通过 pip install pyinstaller 进行安装。
这里建议使用虚拟环境去安装
pyinstaller,它会根据环境中的库情况进行打包,如果使用的库多了会导致打包出来的程序会特别地大。如果在虚拟环境中做库的删改都会更加方便。
开始打包!
完成安装后就可以开始打包的操作了,首先需要 cd 到 .py 文件对应的目录文件夹,这样就可以保证生成出来的文件都在目录里面,整理比较方便。
pyinstaller 常用的命令有两个:
pyinstaller -D app.py
pyinstaller -F app.py
其中的 app.py 为要打包文件的相对地址,-D 是默认命令,即生成一个目录文件,里面包含了一个启动程序和一系列的依赖文件;-F 是生成单个可执行文件的命令,它生成 build 和 dist 文件夹,其中 dist 文件夹里面的可执行文件是可以单独使用的,其余项可以删掉。
它的原理很简单粗暴,就是将 Python 复制出来,连着脚本一起打包进去,执行的时候再全部解压到缓存文件夹里执行脚本文件。
路径问题
打包完成之后就可以拿出来使用了,因为里面集成了 Python 的 runtime 环境,所以不管电脑里面有没有装 Python,各种姿势使用都不会影响。
正当我以为完成之时,打开程序直接闪退。从 CMD 打开才发现程序出现了错误,要访问的文件访问不到,这时我才发现程序执行的目录(一个在 Roaming 中的缓存目录)和这个程序放的目录不是一致的,所以直接用相对地址根本访问不到所需要的文件。
不过幸好 Python 还是有解决办法的,就是获取执行文件所在的路径。
os.path.dirname(os.path.realpath(sys.executable))
os.path.dirname(os.path.realpath(sys.argv[0]))
利用 os 库中的这两个命令都可以返回该执行文件的绝对地址,然后再加在前面就可以解决问题了。
如何减小包的体积
如何减小 pyinstaller 打包程序的体积,这是一个十分具有优化量的工作。我的思路大致如下:
- 建立虚拟环境去进行打包;
- 如果能够 import … from …,就不要 import 整个库,不然也会一起打包;
- 能合起来的功能就合起来,分开打包的同时也会分别集成 Python 环境;
- 能引用外部文件的地方就引用外部文件。
如果体积还是超标,可以考虑换一个框架,比如 UWP 之类的因为 Windows 系统自带框架,所以出来的文件体积都很小。而 eletron 和 swing 这些框架它本身也是要集成一个 Chromium 或者 JDK 的独立环境,所以体积都不小,通常 60M 起步,不过像 VSCode 这样老大哥级别的开发团队,可以通过玄学压缩的方式给 eletron 压到 30M+,还是十分有实力的,在优化上也没小下功夫。