之前寫了個腳本自己平常工作用,最近因為需要把腳本給其他同事用,為了避免它們還需要配置環境,于是用 PyQt 寫了個界面,然后用 PyInstaller 打包成 exe 。打包過程中遇到了一些坑,紀錄一下。
PyQt
之前寫過一個蝦米歌單導出小腳本,exe 版本是用的 Python 自帶的 Tkinter 寫的,所以這次嘗試用 PyQt。寫的時候遇到了任務欄閃爍和打包后程序界面圖標不顯示的問題。
-
任務欄閃爍提示
后臺運行程序的時候,如果使用
QFileDialog
,程序彈出保存對話框的時候會在任務欄閃爍提示。但不是每個 Widget 都會有這個功能,但是這時候可以通過QtWidget
的 activateWindow() 和 QApplication.alert() 來實現,但這兩者使用的時候會有點區別。activateWindow()
是實例方法,只要程序窗口切換到前臺被激活了就不會再閃爍。而QApplication.alert(QWidget, msecs: int = 0)
是靜態方法,msecs
值為 0 的時候,和activateWindow()
的效果一致,但是需要在閃爍停了之后激活程序才會任務欄窗口顏色才會恢復正常,否則還是黃色,直到閃爍停了之后再激活一次程序。msecs
不為 0 的時候,超過這個時間后,任務欄窗口就會自動恢復正常。所以activateWindow()
是比較好的選擇,除非不要求一直在任務欄提示。 -
資源文件在打包時的處理
把代碼用 PyInstaller 打包到一個文件的時候,會出現圖標或圖片都不顯示的情況。這種時候就需要用 Qt’s resource system 來對其進行打包。
首先新建一個 .qrc 文件,內容格式如下:
<RCC> <qresource prefix="/" > <file>img/image1.png</file> <file>img/image2.png</file> <file>img/image3.png</file> </qresource> </RCC>
然后去文件目錄下執行
pyrcc5 -o images_qr.py images.qrc
命令,最后在代碼中 import image_qr.py,并且修改下圖片路徑,一定要在路徑前面加上冒號。import image_qr.py # your code self.setWindowIcon(QtGui.QIcon(':/img/image1.png'))
?
PyInstaller
之前用 cx_freeze 打過包,但感覺不理想,搜索了下發現 PyInstaller 用得比較多,就使用了這個,第一次用的時候沒遇到問題,但是因為 Python 是裝的 64 位的,所以打包之后的程序無法在 32 位的機器上使用。這就意味著我必須要在 Python 32 位的環境下打包,但重新配置了下環境之后,遇到了 ImportError 和無法鏈接到動態庫的問題。
-
ImportError: DLL load failed
用 PyInstaller 給程序打包的時候遇到了
pyi_rth_qt5plugins returned -1
的 Fatal Error 提醒。這個錯誤信息幾乎是毫無用處的,修改 .spec 文件,打開 debug 模式以及顯示 console 后,在running pyi_rth_qt5plugins.py
的時候發生了ImportError: DLL load failed 找不到指定的模塊
錯誤。回頭想起了在編譯的時候看到了很多 WARNNING 消息,回過頭查看,發現了很多
lib not found
的問題。但是仔細檢查了 Python 庫之后,這些 DLL 明明在C:\Python35-32\Lib\site-packages\PyQt5\Qt\bin
目錄下,最后的搜索得到的解決辦法是把這個目錄添加到環境變量里。問題得到了解決,猜測原因是因為之前使用 pip 安裝 PyQt 的時候, pypi.python.org 總是連接不順暢,最后去下了個 .whl 文件直接安裝,導致沒有對應環境變量打包的時候找不到 DLL。
# 環境: Python == 3.5.2 ,PyInstaller == 3.1.1 10951 WARNING: lib not found: Qt5Svg.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\imageformats\qsvg.dll 11206 WARNING: lib not found: Qt5Gui.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\imageformats\qsvg.dll 11437 WARNING: lib not found: Qt5Core.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\imageformats\qsvg.dll 11763 WARNING: lib not found: Qt5Gui.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\imageformats\qtga.dll 12017 WARNING: lib not found: Qt5Core.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\imageformats\qtga.dll 12224 WARNING: lib not found: Qt5Gui.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\platforms\qminimal.dll 12418 WARNING: lib not found: Qt5Core.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\platforms\qminimal.dll 12625 WARNING: lib not found: Qt5Gui.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\platforms\qwindows.dll 12833 WARNING: lib not found: Qt5Core.dll dependency of C:\python35-32\lib\site-packages\PyQt5\Qt\plugins\platforms\qwindows.dll
-
api-ms-win-crt-runtime 錯誤
PyInstaller 打包之后的程序運行的時候發生
api-ms-win-crt-runtime
動態庫之類的錯誤,似乎只有在 Python 3.5 下打包才會遇到。因為 Universal CRT (KB2999226)缺失,可以通過安裝此更新來解決問題。或者直接下載 Visual C++ Redistributable (x86 ,x64 )。參考鏈接:api-ms-win-crt-runtime-l1-1-0.dll is missing when open office file
這次的幾個坑讓我更堅定這類工具最好不要用最新版本,一不見得更穩定,二是遇到問題資料也比較少,在這類不必要的麻煩上花太多時間不值得,除非新版本能有很大的收益。