周日趣事:看看python腳本怎么打包成可執(zhí)行文件(應(yīng)用)

背景

同事A需要在一臺只能訪問局域網(wǎng)的mac mini上運行一個python腳本,腳本依賴了一些模塊,有numpy這種三方模塊,也有自己開發(fā)的本地模塊,而mac mini上除了python,什么都沒有安裝。同事B接到求助后三下五除二生成了一個可執(zhí)行文件,堪稱滿分答案。但對于具體細(xì)節(jié),同事B表示很復(fù)雜說不清,于是就有了姑娘的周日趣事。

工具

淺百度一下,迅速定位到工具為PyInstaller, 查到官網(wǎng)上有以下描述,確認(rèn)就是你沒錯!

PyInstaller bundles a Python application and all its dependencies into a single package. The user can run the packaged app without installing a Python interpreter or any modules.

從首頁的描述來看,使用簡直不能再簡單:
安裝工具:

pip install -U pyinstaller

使用工具:

pyinstaller your_program.py

真的這么簡單嗎?

如果同我一樣順手用了import numpy做demo的話,就不是了!
我的腳本tryPyinstaller.py:

import numpy as np
print("6 / 3 = " + str(np.divide(6,3)))

使用工具:

pyinstaller --onefile tryPyinstaller.py

運行生成的應(yīng)用:

(base) leixiaoyues-MacBook-Pro:~ leixiaoyue$ /Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller ; exit;
INTEL MKL ERROR: dlopen(/private/var/folders/fq/qx5csyvd54x6p60p38qvqfpm0000gn/T/_MEI8YGfHc/libmkl_intel_thread.1.dylib, 0x0009): Library not loaded: '@rpath/libiomp5.dylib'
Referenced from: '/private/var/folders/fq/qx5csyvd54x6p60p38qvqfpm0000gn/T/_MEI8YGfHc/libmkl_intel_thread.1.dylib'
Reason: tried: '/usr/local/lib/libiomp5.dylib' (no such file), '/usr/lib/libiomp5.dylib' (no such file).
Intel MKL FATAL ERROR: Cannot load libmkl_intel_thread.1.dylib.
logout
Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

為什么會缺庫???!這件事情還不得而知,選擇暫時放過自己,先來解決問題現(xiàn)象!這就引出了PyInstaller一個非常重要的機(jī)制——鉤子!

鉤子??萬歲

淺百度一下,又在官網(wǎng)中看到有“Understanding PyInstaller Hooks”一節(jié),大概感到有救。鉤子是編程中用來實現(xiàn)可拓展性的一個常用技巧。鉤子已在!缺什么鉤什么!

接下來看看PyInstsaller里具體怎么鉤,抄 StackOverflow上的作業(yè)。

  1. 新建鉤子腳本hook-numpy.py,把要鉤的庫列在里面

from PyInstaller import log as logging
from PyInstaller import compat

from os import listdir

mkldir = compat.base_prefix + "/lib"
logger = logging.getLogger(name)
logger.info("MKL installed as part of numpy, importing that!")
binaries = [(mkldir + "/" + mkl, '.') for mkl in listdir(mkldir) if mkl.startswith('libmkl_')]

  1. 通過參數(shù)additional-hooks-dir告訴程序新增鉤子的路徑,參數(shù)clean是為了清除之前運行的緩存,多個香爐多個鬼,清一清沒啥不好

pyinstaller --additional-hooks-dir=. --clean --onefile tryPyinstaller.py

雙擊應(yīng)用,成功運行

Last login: Sun Apr 9 15:02:31 on ttys008

The default interactive shell is now zsh.
To update your account to use zsh, please run chsh -s /bin/zsh.
For more details, please visit https://support.apple.com/kb/HT208050.
/Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller/tryPyinstaller ; exit;
(base) leixiaoyues-MacBook-Pro:~ leixiaoyue$ /Users/leixiaoyue/Code/YuePythonScript/tryPyinstaller/dist/tryPyinstaller/tryPyinstaller ; exit;
6 / 3 = 2.0
logout

Saving session...
...copying shared history...
...saving history...truncating history files...
...completed.

[Process completed]

運行是真的慢……

工程師的工具箱里又多了什么

首先,是把所有依賴統(tǒng)統(tǒng)打包成應(yīng)用的思路。這在幫完全外行的朋友寫軟件時超級有用,這樣簡單直接的思路以前還真沒想到過。
再就是又一次領(lǐng)略了??提供可拓展性的魅力。

解決舊問題帶來新問題

為什么打包出來的程序運行那么那么慢……
為什么打包numpy會缺libmkl_xxx一系列Math Kernal Library?
Hook 真的是個好的命名嗎?韓語??(hooking),日語フック(hook),直接用音譯,大陸譯作“鉤子”,不能在亞洲圈獲得統(tǒng)一的翻譯,往往是命名不夠準(zhǔn)確的一個表現(xiàn)……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容