Python GUI開發之打包的那些坑(PyInstaller)

開發環境:win10+python3.6+pyqt5+pyinstaller3.4


前言

利用pyqt5開發了一個小工具,開發完成之後需要打包成EXE以供其他人方便地使用。這裏的打包工具網上99%的人都推薦使用pyInstaller。也就一腳踏入了這個深坑。。。

斷斷續續用了兩三次來做這個打包(在開發迭代過程中):

  1. 第一次摸索了一下,簡單的依賴包的可以很方便的成功,太多依賴的就很容易失敗,未深究,暫時放棄;
  2. 第二次花了點時間在網上一頓搜索,終於我的代碼也成功的打包了,但還是理解的不夠深入。
  3. 第三次也就是這一次了,軟件功能基本上完成,那現在打包已經是迫在眉睫的事了,所以專門花了兩天好好的學習了一下官方文檔(並未看完…),終於一頓“百度”之後終於算是取得了階段性成功。

現在講經歷的一些坑以及解決方案分享如下(也方便自己以後再遇到同樣bug的解決,哈哈):


分享會

1. VCRUNTIME140.dll沒有被指定在Windows上運行

這個問題的解決主要參照了這篇文章
總結一下: 原因應該是upx 將VCRUNTIME140.dll給壓縮了,但具體深層次的原因我就不清楚了(攤手…)但是編輯了.spec中的upx=False(也可以在命令行指定參數–noupx)即不使用upx壓縮可以解決此問題。

2. AttributeError:’str’ object has no attribute ‘items’

與此問題類似的錯誤還有ModuleNotFoundError: No module named 'setuptools._vendor'
因此這個問題的解決主要參照了這篇文章
總結一下: 這個問題應該是setuptools版本的問題,使用pip install --upgrade setuptools更新一下版本即可解決。

3.打包成功後,運行.exe報錯: ModuleNotFoundError: No module named ’numpy.core.__dtype_ctypes’

直接運行軟件會閃退,可以通過PowerShell(Windows)來運行查看錯誤,與此類似的還有ModuleNotFoundError: No module named ’sklearn.neighbors.typedefs’,解決方案類似。
總結一下: 這些問題主要從GitHub上該項目的issue模塊得到了解決方案(我們不是孤獨的,大家都遇到了同樣的問題)
可以通過兩種方式得到解決:

  1. 第一種是hooks(這也是作者推薦的方式),這是一種更優雅但是卻不是最方便的方式,如標題的錯誤我是這種方式解決的:
    將下述代碼放到hook-numpy.core.py文件裏(當然你需要把這個路徑在命令行或者.spec中告訴pyinstaller)。
hiddenimports=['numpy.core._dtype_ctypes']
  1. 更多的我採用的是第二種方法:直接在hiddenimports中指定(也可在命令行參數中指定,詳見下文)。

pyinstaller使用總結

如果打包過程中遇到問題建議將打包過程分成兩步來做:

1. 轉換.py爲.spec

pyi-makespec --noupx -w ^
             --icon=../icons/app.ico ^
             --additional-hooks-dir=../hooks ^
             --hidden-import=sklearn.neighbors.typedefs ^
             --hidden-import=sklearn.neighbors.quad_tree ^
             --hidden-import=sklearn.tree._utils ^
             main.py

這是我第一步用到的命令(包含了不用upx壓縮,打包出來不需要console,指定icon,指定hooks路徑,以及一些hiddenimport的庫),直接將該命令複製到控制檯運行,即可在該目錄下生成main.spec

2. 生成 .exe

這部分只需要一句命令:
pyinstaller main.spec

經驗

  1. Using Spec Files
  2. 多看官方文檔,
  3. 多搜GitHub issue下的問題。

未解決的問題

  1. 參考官方文檔Hiding the Source Code以及此文章嘗試了一下將腳本編譯成pyd(動態鏈接庫)的防止反編譯方法。但是報錯:#error: Unable to find vcvarsall.bat
  2. 由於pycrypto只支持到了python3.4,因此想要實現官方文檔所說的Encrypting Python Bytecode,在python3.6版本下好像就有點麻煩了,失敗…
針對上述兩個如果哪位大俠有比較好的解決方案,請告知,非常感謝。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章