pychaim下PyInstaller 打包 python程序
主題是使用PyInstaller 打包python時遇到一些問題以及解決方案,其中將要打包的程序是用tensorflow做的LSTM算法,這里不會涉及這個算法詳解。
本地環境:window 10 服務器環境 windows2008
原文地址:原文
主要運行時版本依賴
python 3.6
PyInstaller 3.4
tensorflow 1.4 (過程中更新為1.7,原因下詳)
jieba 0.39
wordcloud 1.5
安裝與使用PyInstaller
在pychaim下可以直接打開下方Teminal 窗口 執行指令
pip install 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,y1),(x2,y2)]
x1:是指需要打包的資源文件位置,可以是文件夾名稱(我這里是static),單一文件,或者 帶有通配符 * 的多個文件。
y1:是指需要輸出到臨時文件夾內的相對地址。這里我用了點符號 (.),代表臨時文件夾本身。
這樣需要的資源文件就包括進去了,也能正常讀取了。
有其他辦法是修改源碼的,其實是很不優雅的。
四,No module named 'tensorflow.contrib'
這個異常在測試環境是沒有的,只有打包之后運行才出現,原因是tensorflow.contrib 這個庫是懶加載的,所以打包程序沒有包括進去,只有在運行時才發現少了。
這里還是可以通過修改spec文件來隱性導入,就是上圖里面的
hiddenimports=['tensorflow.contrib'],
結尾:引用請注明出處與作者
參考文獻: