Jasper Ji

开口不在舌头上

0%

Python打包exe

Python平时主要是处理数据用,在Mac上使用很方便,最近想把一个程序让下面人用,他们是Window环境,Python他们并不熟悉,所以直接把源文件丢过去,他们又得折腾一番。我就想到打包成exe,其实很早就有这样的想法,但一直没有做过。用的是PyInstaller这个库,还想着这么简单,结果一打包,发现并不是Window下的exe,原来是我理解的错误,以为可以直接打包成Window上执行的exe了,实际上PyInstaller只是在不同平台上将python打包成对应平台的应用了。难道我又得找台Windows,环境弄好,再打包一个?真麻烦,想着可以交叉编译吗?查了下PyInstaller以前好像可以,后来就去掉了。之前用过点Go语言,就是可以交叉编译的,一时间我尽有想用Go重写那个功能的想法,但是一对比还是Python方便。最后找了一个通过docker进行打包的方案docker-pyinstaller

直接这个命令就可以打包了,具体可以参考文档。

1
docker run -v "$(pwd):/src/" cdrx/pyinstaller-windows

但是有个问题,打包出来的应用一执行,提示一个依赖的库,没有找到。不对啊,文档中明明说把依赖写在requirements.txt文件里,我也写了的。

文档中的这段话,看着没有其他的操作,也没有相关的示例代码。

If the src folder has a requirements.txt file, the packages will be installed into the environment before PyInstaller runs.

折腾了好几个小时,最后找到了一篇日文的文章,看完后豁然开朗,原来是写法的问题,我对docker的一些东西不够熟吧。

1
2
3
4
5
docker run --rm -v "$(pwd):/src/" cdrx/pyinstaller-windows -c \
"pip install -r requirements.txt && \
pyinstaller main.py --onedir --onefile --clean && \
mv dist/main.exe main.exe && \
rm -rf __pycache__/ build/ dist/ main.spec"

最后打包后的exe就没有依赖缺失的问题了。不过打包成exe后,我最终还是改了下python的代码,比如os.path.dirname(__file__)是无法使用了,另外打开文件时提示UnicodeDecodeError: 'gbk' codec can't decode byte的错误,需要加encoding='utf-8'

参考

Docker環境のPyInstallerでキレイにExe化する