前言
在使用python開發好一款軟件、工具之后,我們希望能夠把這個軟件發給其他人使用,就像我們使用其他軟件一樣,只需要雙擊打開exe,而不需要管其他環境。
對於類似C、C++而言是在系統編譯的時候就生成了exe,然后只需要把exe和所需環境一起打包即可。但是對於Python這種解釋型語言而言,不能通過這種方式生成可執行程序。
當然,python也有對應的處理辦法,其中常用的就是PyInstaller包。
PyInstaller介紹
1. 安裝介紹
PyInstaller包並不是python默認安裝模塊,需要用戶手動安裝,安裝方式如下:
pip install pyinstaller #或 conda install pyinstaller #對於一些裝不成功的模塊,可以考慮如下方式,以pydicom為例 conda install -c conda-forge pydico
pyinstaller -F -p XXX/Lib\site-packages XXX.py
2.使用介紹
切換到需要打包的python路徑下,然后再打包。是不是必須這樣需要打個問號,沒有做實驗,理論上應該只需要包含需要打包python文件全路徑即可,可能切換到文件路徑下更方便。
PyInstaller 常用使用方式如下:
pyinstaller -F -w xxx.py
-F: 打包成exe;-w:exe不顯示控制台,默認顯示(-c);xxx.py需要打包的python文件
具體pyinstaller打包工具的詳細參數可以參考博文:https://blog.csdn.net/weixin_39000819/article/details/80942423
安裝成功后出現如下圖:
PyInstaller打包過程中遇到的問題及解決辦法
1.打包后的exe出現閃退
對於一個簡單的測試用例,打包完成后,雙擊exe之后就可以打開,如下圖所示:
但是當你在程序中引用了其他包的時候,畫風就發生改變了,例如我在系統在中引入了numpy包,按照上面的方式打包,雙擊打開exe后就出現了閃退的情況。
剛開始的時候一頭霧水,完全不知道發生了什么,面對這種情況怎么處理呢?
2. exe閃退問題排查
在這個時候打包的時候-c參數就起作用了,-c參數(默認參數)是打包成一個帶有后台的exe,可以看到調試信息、打印信息、報錯信息等,因此只需要把這個exe拖到cmd下面查看報錯信息就可以定位問題了。
一看,發現是缺少numpy模塊。對於我不熟悉python打包的我,有點懵,還以為只需要按照上面的打包方式一頓操作就萬事大吉了,沒想到其實不是,也會遇到模塊丟失的問題,讓我想起的C++生成的exe,也是需要配套include、dll支持的。因此,猜測需要把所需要的模塊放到exe目錄下。
我做了嘗試,但發現依然不起作用,當然有可能是我放置的路徑不對,或者包不全等原因。總而言之是沒成功!
3. 模塊缺失解決辦法(ModuleNotFoundError)
可是如果真的要通過手動考包的方式考過去,會不會有點太麻煩,因此查到了另外的處理方式,也就是在打包的時候把依賴庫也打包進exe,不得不說這就是我期待的方式。
那具體怎么操作呢?
我們知道安裝的庫一般都是在"***/Lib\site-packages"文件夾中,也就是打包的時候把這個包打進去即可,看到很多博文提到這種方式確實解決了問題。
例如這篇就寫得很好 https://www.cnblogs.com/Summerio/p/11676943.html
廢話不多說,具體操作如下
pyinstaller -F -p ***/Lib\site-packages XXX.py
看到這里,多了個-p參數,-p后面就是需要打包的庫路徑,這里是支持打包多個路徑的,只需要繼續-p +路徑即可。打包完成之后,可以看到新生成的exe的體積明顯更大了。
但是很不幸,又遇到了其他的問題。打開exe依然失敗了。
但是錯誤信息有些不一樣。
這個就很詭異了,於是我看了下打包的過程中,是不是真的對了。結果還真是,打包的時候就出現問題了:
這個就很奇怪了,看起來像是找不到numpy包,但我明明安裝了。為了證明這個猜想,我就用當前環境的python導入numpy試試看,發現還真不行。
4. python環境問題
很是奇怪,因此我猜想是python環境的問題。python使用的庫site-package並不是當前環境的site-package(本人使用的是anaconda)。如下方式可以證明:
(1)查看當前python路徑,確定環境
import sys sys.executable
(2)查看當前python環境使用的site-package路徑
import site site.getsitepackages()
(3)結論:可以看到python並么有使用當前虛擬環境的site-packages,當前site-pacakges的路徑是D:\miniconda3\envs\testPackage\Lib\site-packages
因此引起了如上的錯亂。。。。
具體原因還沒有查到,看到一篇可能的原因是,conda沒有對用戶的site-packages,大家可以先看看
https://zhuanlan.zhihu.com/p/361712304
5. exe找不到包的子模塊,及對應解決辦法
然而,真的是好事多磨,又遇到了其他問題了。因為我用到了pydicom這個模塊,發現打開exe后,找不到對應的子模塊:
很神奇,弄得我都懷疑這種打包方式對不對,不然為什么會找不到pydicom的子模塊。
不過幸好,找到了對應的解決辦法。也就是打包的時候,將找不到的模塊也一一打包進去:
pyinstaller -F -p D:\miniconda3\envs\fullPhaseSeparate\Lib\site-packages --hidden-import="pydicom.encoders.gdcm" --hidden-import="pydicom.encoders.pylibjpeg" main.py
如上,使用--hidden-import="libname"的方式打包對應的子模塊。
具體參考文章如下:
成功
成功!激動之情溢於言表!
到這里為止!我這曲折的打包過程終於完事了!exe也發出去可以正常使用了!
希望對大家有絲絲幫助~
同時,歡迎大家溝通交流!