linux環境下使用pyinstaller分步打包python程式(使用spec檔案將python程式打包成一個可執行檔案)
先貼上pyinstaler的官網指南,很多使用方法可以直接查到:
-
pyinstaller的安裝:
在自己的環境下執行:
pip install Pyinstaller
有什麼錯誤就根據錯誤提示去查,這個容易解決~
-
pyinstaller的初步使用:
進入程式所在的目錄下,命令列直接執行:
pyinstaller XX.py # XX換成自己的檔名
執行可以在該目錄下得到兩個資料夾dist和build,還有一個XX.spec檔案,需要的可執行程式就在dist資料夾下。如果你的python程式沒有使用外部檔案,這時候進入dist資料夾下,命令列中使用 ./ 執行該檔案即可執行。
遇到一些錯誤如no module ...,很有可能是pyinstaller沒有自動匯入你呼叫的第三方庫,這裡貼幾篇文章作為參考。
-
pyinstaller分步生成可執行檔案
上一步中我們可以看到生成了一個spec檔案,簡單情況下,我們使用pyinstaller的一些options選項就足夠了,但在一些其他情況下,我們可以通過修改spec檔案,來對我們生成可執行檔案的過程進行自定義。
生成spec檔案可以通過命令:
pyi-makespec options name.py
其中,options和pyinstaller的options幾乎一致,可以參考官網文件:
這裡,我使用的命令如下:
pyi-makespec present_fasttext_txt.py -F --hidden-import fasttext.model
這樣生成的就是一個單一執行檔案
生成的spec可以開啟編輯:
# -*- mode: python -*- block_cipher = None a = Analysis(['present_fasttext_txt.py'], pathex=['/home/km/PycharmProjects/fasttext'], binaries=[], datas=[], hiddenimports=['fasttext.model'], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, name='present_fasttext_txt', debug=False, strip=False, upx=True, runtime_tmpdir=None, console=True )
因為加了-F引數,所以沒有coll內容(查閱官網文件可以知道這個是用來在dist目錄下生成程式資料夾的)
當我們需要新增資原始檔時,在datas那個list中新增相應tuple,tuple的元素是兩個字串,第一個意為呼叫的資原始檔在系統下的路徑,第二個是該檔案相對於生成的程式的路徑,新增之後該spec檔案如下:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['present_fasttext_txt.py'],
pathex=['/home/km/PycharmProjects/fasttext'],
binaries=[],
datas=[('comment_fasttext_isinv.model.bin','.'),('comment_fasttext_isneg.model.bin','.'),('comment_fasttext_issug.model.bin','.'),('comment_fasttext_isbug.model.bin','.'),('comment_fasttext_ispraise.model.bin','.')],
hiddenimports=['fasttext.model'],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='present_fasttext_txt',
debug=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=True )
可以看到我修改了datas部分,由於我呼叫的檔案就在我的當前目錄下,所以我直接寫的檔名,如果呼叫其他目錄下的檔案,要寫全名的,後面的‘.’,表示它存在程式的根目錄下。
這樣修改完了,執行:
pyinstaller present_fasttext_txt.spec
即可。
之後進入dist資料夾下,發現可執行程式比較大,大概有80M,應當是把資原始檔打包進去了。執行程式,發現報錯。顯示找不到檔案,經過排查發現原來還有關鍵的一步沒做。
-
打包成一個exe之後資原始檔的路徑問題
之前的py程式中,由於資原始檔直接放在專案根目錄下面,所以呼叫的時候直接用的檔名。這導致,後面打包成exe檔案的時候,呼叫資原始檔時會在dist資料夾下搜尋檔案,當然,我的檔案打包到exe檔案中了,這樣呼叫顯然會出現找不到相應檔案的錯誤,所以,我們還要對python程式部分進行路徑上的修改。
參考博文:
要定義一個讀取相對路徑的函式:
import os, sys
def resource_path(relative_path):
"""
定義一個讀取相對路徑的函式
"""
if hasattr(sys, "_MEIPASS"):
base_path = sys._MEIPASS
else:
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
我之前的呼叫示例如下:
classifier1 = fasttext.load_model("comment_fasttext_isinv.model.bin", label_prefix='__label__')
修改之後為:
classifier1 = fasttext.load_model(resource_path("comment_fasttext_isinv.model.bin"), label_prefix='__label__')
修改程式後,再打包,一切ok~