pychaim下PyInstaller 打包 python程式
pychaim下PyInstaller 打包 python程式
主題是使用PyInstaller 打包python時遇到一些問題以及解決方案,其中將要打包的程式是用tensorflow做的LSTM演算法,這裡不會涉及這個演算法詳解。
Python學習資料或者需要程式碼、視訊加Python學習群:960410445
本地環境:window 10 伺服器環境 windows2008
主要執行時版本依賴
python 3.6
PyInstaller 3.5
tensorflow 1.4 (過程中更新為1.7,原因下詳)
jieba 0.39
wordcloud 1.5
安裝與使用PyInstaller
在pychaim下可以直接開啟下方Teminal 視窗 執行指令
pipinstall PyInstaller
打包python程式
PyInstaller-F XXXX.py
-F 是把所有的相關程式都打包成單個exe執行檔案。
執行過程中會在當前專案根目錄下 新建2個資料夾 build ,dist 與一個檔案 XXXX.spec
build資料夾是在打包過程中臨時存放所有中間檔案的地方
dist是打包完成後的exe儲存位置
XXXX.spec 與 打包時XXXX.py 是同名檔案,自動生成了一份描述性檔案,用來告訴pyinstaller 如何打包這個py程式。
所以一旦自動生成了一個spec檔案 後續可以根據需求自行修改 spec檔案,然後執行
PyInstaller-F XXXX.spec
遇到的問題
一,AttributeError: module ‘enum’ has no attribute ‘IntFlag
這個問題有文獻1可知,是由於tensorflow 1.4 版本依賴了 enum34 這個庫導致的錯誤,所以我升級為1.7 解除安裝掉了enum34庫
二,tuple index out of range
這個異常是由文獻2可知,pyinstaller當前版本不支援 python3.6 所以需要從GitHub那邊下載develop版本替換掉本地的版本。
三,No such file or directory: 'c:xxxx\jieba\dict.txt'
由於接入了jieba庫,因為該庫裡面用到了一些預設的資原始檔如 dict.txt idx.txt 等,
這個疑問參考issue 文獻3 ,但是解決方案治標不治本,另外還有很多資原始檔都無法載入 如:wordcloud 中就載入了預設的 stopword 停用詞字典。
因為在pyinstaller 打包後的exe 執行時會在 C:\Users\Administrator\AppData\Local\Temp 新增了一個臨時資料夾如“_MEIxxxxxx” 所有py程式碼都會在臨時存放在這裡,
所以很多第三方庫中如果使用了 __file__ 如下示例:(wordcloud原始碼)
FILE= os.path.dirname(__file__)FONT_PATH= os.environ.get('FONT_PATH', os.path.join(FILE,'DroidSansMono.ttf'))STOPWORDS= set(map(str.strip, open(os.path.join(FILE,'stopwords')).readlines()))
jieba庫也有類似載入方式。
會導致執行時__file__ 指向了上面說的臨時資料夾“_MEIxxxxxx”,所以就會報錯,說找不到該檔案,無法開啟。
一勞永逸的辦法是修改 spec 檔案.
先把一些需要載入的資源按照第三方庫預設的檔案結構放在 static(這個名字隨你定) 資料夾內 ,如下圖
然後根據官方文件參考文獻4,修改spec的datas 節點
datas接收一個元組陣列 [(x1,y2),(x2,y2)] x1 是指需要打包的資原始檔位置,可以是資料夾名稱(我這裡是static),單一檔案,或者 帶有萬用字元 * 的多個檔案。 y1,是指需要輸出到臨時資料夾內的相對地址。這裡我用了 點符號,代表臨時資料夾本身。
這樣需要的資原始檔就包括進去了,也能正常讀取了。
有其他辦法是修改原始碼的,其實是很不優雅的。
四,No module named 'tensorflow.contrib'
這個異常在測試環境是沒有的,只有打包之後執行才出現,原因是tensorflow.contrib 這個庫是懶載入的,所以打包程式沒有包括進去,只有在執行時才發現少了。
這裡還是可以通過修改spec檔案來隱性匯入,就是上圖裡面的
hiddenimports=['tensorflow.contrib'],
結尾:
作者:鬼柒