最近接了一個案子,案主的需求是簡單的網路爬蟲,需要從網頁上抓些資料,處理之後再供給 Excel 透過 VBA 顯示、處理。一開始,我是用 Windows 10 上的 BASH Shell Script 驗証概念,確定可以後再移到 Python 上。
Python 寫好後為了達成方便使用,就去看怎麼把 Python 打包成執行檔,不然程式拿到其它機器都要先裝 Python 也太麻煩。由於還利用到了一個 Tidy 的 HTML 美化 Library,算是一個比較完整的打包需求,就寫篇文章把這個流程記下來。
Python 版本
這篇文章是利用 Python 2.7.15 x86寫的,在 Python3 下面則沒有驗証過。 Python 2.7.15 在安裝時都已經考慮的的蠻周全了,環境變數、PIP 都已經一併安裝設定好。裝過早期的 2.7.0,這些都還要手動安裝,因此建議可以直接用 2.7.15 後的,以保証流程會跟我相同。
另外, 也建議安裝 x86 版本。我們稍後會用 3rd party 的預先編譯 Pytidylib, 其不需要 VC10/VC14 的 Runtime library,這對於打包直接使用的 .exe 檔是蠻方便的,因為不需要再另裝 VC Runtime Library。若是使用官方的 Tidy Library, 則有這個要求。但3rd party的檔案只提供 x86版本的,若裝x64版本,則此 library 就無法使用。
安裝
![](https://i2.wp.com/moon-half.info/wp-content/uploads/2018/09/01.png?resize=300%2C257&ssl=1)
將執行檔加入PATH
Python 安裝,基本上就是一直下一步就好了。稍微要注意一點的,就是安裝時要將 python.exe 加入 PATH 內,以便在命令視窗就可執行。
安裝 Pyinstaller 與原理
要將 python 的程式打包成單一的Windows執行檔,用的正是 Pyinstaller 這個套件。
它的原理是偵測 python 腳本所用到的所有套件,並將它們搜集後連同 python.exe 打包起來,轉換成一個執行檔。在執行這個檔案時,會先將檔案解壓縮到暫存區,再執行它們。以此方法,就可達成將python程式封裝成單一檔案。
安裝 pyinstaller 則是利用簡單的套件安裝命令 pip install pyinstaller 就可以完成。
Python 程式打包成執行檔
一切裝好後,我們以一個最簡單的 ‘Hello World!’ 程式為例子,將之打包成執行檔。
1 |
print "Hello! World!" |
打包的命令
1 |
pyinstaller -F hello.py |
這樣就會生成一個 hello.exe 在 dist/hello.exe 了。
加入 Pytidylib
在客戶的應用裡需要用到 Tidy。Tidy 是一個將 HTML 美化的函式庫,它分成兩個部份,Python 套件與一個 Windows DLL。一般開發時,將 DLL 與 Python 腳本放同一目錄,或放在 C:\Windows\System32內。而在打包成執行檔時,亦要將其加入打包的檔案內。
安裝 pytidylib
PyTidyLib 的官方網頁有提到相關的資訊,pytidylib 需搭配 HTML Tidy,其僅是一個對 DLL 的介面。 pytidylib 可直接使用 pip 安裝。
1 |
pip install pytidylib |
HTML Tidy 的 DLL 可在其官方網頁下載頁下載,將其解壓縮後,取得 bin/tidy.dll。將其複制一份到 C:\Windows\System32 與 python 腳本下。這樣在執行與打包時,皆可方便使用。官方的DLL檔是用 Visual C++編譯的,因此會要求另外安裝 Runtime Library,這個在打包.exe時會造成不方便,需要要求使用者也安裝 Runtime Library。也許也可以試著將用到的 VC Library 打包進去,但我們這邊使用的方法是用 3rd party 的單一 DLL 檔案。
網路有找到一家公司,有提供預先編好獨立的 Tidy Library,不需要再安裝其它 Library。本文是選用這個方案,文末也會附上,以免將來 Link 遺失。
使用 PyTidyLib
下面是一個最簡單的 Pytidylib 範例,直接將一個文字的 HTML 美化。實用上可搭配 Web 下載套件,下載後再美化輸出。
1 2 3 |
from tidylib import tidy_document formatted, errors=tidy_document("<table><tr>abc</tr></table>") print formatted |
上面的檔案,執行後會輸出格式化後的 HTML,畫面如圖。
![](https://i2.wp.com/moon-half.info/wp-content/uploads/2018/09/02.png?resize=300%2C197&ssl=1)
Tidy 輸出結果
Pyinstaller + Tidy Library 打包
若要將使用 DLL 的 Python 程式打包成執行檔,則要將 DLL 也加入檔案內。我們使用 Pyinstaller 的參數 “–add-binary” 來將之加入。因此,完整的打包命令是
pyinstaller -F –add-binary libtidy.dll;. tidy_ex.py。
add-binary 命令後面接的參數,是指定將(目前目錄下)libtidy.dll加到執行檔內的根目錄,而中間是用分號(;)隔開。程式的 HELP 有提到也可以用冒號(:)分開,但實用是不行,這點要注意。
被防毒軟體判定為病毒
Pyinstaller (或其它 Python to EXE) 打包出來的程式,有時會被判定為病毒,這跟你程式中使用的 Library 也有相關性。為了避免這個問題,可以考慮用自然人憑証簽署程式,以獲得防毒軟體的信任。
結語
將 Python 檔案打包成單一執行檔,實際上就成了所謂的綠色軟體,使用前不需再裝其它程式。但在交附程式時,其實並不是很喜歡交附執行檔,怕中毒害了人家,資料損毀搞不好還有賠償責任。因此這方面也是需要注意的。另外這邊 Pyinstaller 的測試也是簡單的示範,若有多檔案、多 add-binary的需求,也要請使用者自行嚐試了。
附件
3rd Party 的單一DLL x86 Tidy Library
請問一下,不安裝pyinstaller,可以用別的軟體或方法,把python檔案,轉成exe檔嗎?
cheesan
我想就算有不同的程式,原理還是類似吧,你可以直接 Google 「pyinstaller alternative windows」,還是有其它的程式可以用。
感謝蔡大哥,因為我用pyintstaller 編譯成exe,但是不是缺upx,就是缺Fix,還有
395 WARNING: Several hooks defined for module ‘win32ctypes.core’. Please take care they do not conflict.
這個小心他們不衝突是什麼意思?
Cheesan
這個問題我沒碰到,所以也沒辦法回答你。建議可以用和文章裡一樣的 Python 版本試試,這樣比較會有一致的結果~~~