Day 29 打包安裝PyInstaller:誰把誰的靈魂,裝進誰的身體
註:本篇文章同步刊載於iT邦幫忙,為鐵人賽之系列文章。
https://ithelp.ithome.com.tw/articles/10247305
因為按照慣例,第三十天主要會講比較偏向結論性質的東西,
包含接下來可能的學習方向以及建議,
所以讓我們今天用PyInstaller來做技術方面的最後一章,
恭喜各位讀者,這系列如果都有扎實的跟上的話,
應該能對Python有一些基本的認識。
PyInstaller是一個用來打包安裝Python檔案的函式庫,
一般狀況下,使用pip可以輕鬆將其安裝:
| |
為什麼我們會需要PyInstaller呢?
一般狀況下有幾個可能:
- 你不想直接讓別人看到程式碼(註:但會破解的還是做得到XD)
- 你在開發過程中用了一些函式庫,
這些函式庫並非內建的,從而別人要用你的.py檔執行的話,
會需要進行其它的pip install或準備工作。
這樣很麻煩很不方便,
你希望拿到的人最好可以滑鼠點兩下就可以執行才對XD
這時候使用PyInstaller就可以達成這樣的目的,
除了可以給定簡單的加密外(防君子的那種),
它還可以將整個程式連同用到的函式庫一起打包成執行檔!
我們這邊使用前面的tkinter的範例,
讀者應該會用到的檔案就是fromzero.py和unicorn.ico,
還沒做過的同學,請參照Day 22的範例及Day 23的修改部分。

為了測試,
我們再手動加上一個其實我們沒有在這個範例使用的numpy,
請在fromzero.py中額外加入這行:
(因為它是額外pip安裝的,藉此我們可以觀察一下差異)
| |
PyInstaller的使用方式是直接在命令提示字元下指令,
使用pyinstaller -h可以查看help提示:
| |
我們簡單介紹一下幾個常用的參數部分:
(前面和後面是相同的效果,只是使用縮寫)
-h, — help :顯示help提示說明各參數用法
-F, — onefile :打包成單一一個執行檔
-D, — onedir (預設) :打包成一個資料夾,內含一個執行檔
-y, — noconfirm :
— clean :清空前面打包時產生的暫存檔案
-n NAME, — name NAME :將NAME做為app名字並命名到執行檔
(預設會是主程式原先的主檔名 )
— add-data <SRC;DEST or SRC:DEST> :
將非二進位檔案加到打包中,
SRC對應原先的檔案,DEST對應打包後放的相對資料夾位置
-p DIR, — paths DIR :如果有額外需要import的函式庫時,
告訴pyinstaller可以去DIR這個位置搜尋
— key KEY :用key來加密Python的bytecode
-w, — windowed, — noconsole :在Windows執行時隱藏命令提示字元的視窗
那麼,我們先試試看最基本的打包:
| |
在預設的狀況下,會產生幾個目錄:
pycache(主程式編譯的bytecode檔),
build(編譯過程中產生的檔案),
dist(最終執行所需要的執行檔及其他資料)
我們切換到dist\fromzero的資料夾以後,
應該可以看到fromzero.exe,以及其它的一些檔案及資料夾,
當中就包含了tk和numpy,
顯然pyinstaller自動幫我們評估將函式庫給包進來了!
那麼,在命令提示字元打fromzero.exe,
或者在資料夾中連點兩下就可以執行了……咦?
| |
顯然我們的獨角獸並沒有被包進去,
由於前面我們讀取檔案時,是在和.py相同的資料夾,
所以我們可以將unicorn.ico複製到dist\fromzero的資料夾 ,
就可以正常執行了。
當然這顯然不是很理想,所以讓我們回到上一步,
處理一下圖片的部分。
我們先用以下的方式,將unicorn.ico轉成二進位制,
再存到一個.py檔做為變數img:
(註:參考自CSDN blog)
(如果是一般檔案,則可以使用 — add-data=’SRC;DEST’的方式即可)
| |
此時資料夾中會多出一個icon.py,
裡面就是img=”……”的格式。
接著我們要修改我們的fromzero.py,
從讀取原本的icon,改成從icon.py取得變數:
| |
我們在重新下一次指令:
| |
這時候應該同樣可以在dist資料夾看到fromzero.exe,
且由於我們下了-w,所以執行時後面不會出現命令提示字元了!
如果要進行簡單加密的話,
pyinstaller預設是使用tinyaes:
| |
安裝後,打包時額外加上 — key=”(16個字元的字串)”即可,
少掉的字元會補0。
例如:
| |
如果你覺得這樣子還不夠放心,
可以再透過obfuscator或PyArmor之類的軟體,
將主程式進行混淆以後再打包,
效果會更好呦XD!
最後要留意一點,
如果想要編譯出能在32位元的電腦運行的程式,
則需要使用32位元版本的Python才可以。
那麼,我們就明天見囉!
工商時間:
抽獎活動還在繼續累積人數(現在好像沒有人想抽XD)
在Python Taiwan的連結第100篇的文章 底下,
公開分享到你的臉書、按讚該篇文章、並留言告訴我說,
「你最喜歡這一整個系列的哪一篇?為什麼?」或
「除了從LeetCode學演算法系列以外,
你還想要看到關於什麼方向的文章?」
超過20則留言的話 (有完成以上步驟的才算),我們就抽一組
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」
課程的免費兌換券進行贈送!
期限嘛…就延長到滿人數吧XDD (不然也沒辦法哈哈)
容筆者工商一下,
「從Leetcode學演算法|進階篇」 開放預購啦!
這次選了40道難度加深的LeetCode題目,
同樣也會細部解說對應的技巧及須要掌握的演算法!
同時這次購買進階篇的話,
額外還加贈**「從Leetcode學演算法|面試篇」** !
當中包含了面試準備須知分享 ,及訪談國內外不同經驗的工程師 ,
讓你不論是想走前端/後端/一般軟工 或者是想找國外的工作 ,
是初學想轉職 還是正在工作 ,都能夠從中得到收穫呦!
有興趣的朋友可以使用下面的早鳥優惠~
「從Leetcode學演算法|進階篇」+「從Leetcode學演算法|面試篇」 :
https://bit.ly/leetcodeadv
「從Leetcode學演算法」全套(基礎/進階/面試篇)同捆優惠:
https://bit.ly/leetcodeall
