用 PyInstaller 打包基于 PyQt 的程序遇到的坑

之前寫了個腳本自己平常工作用,最近因為需要把腳本給其他同事用,為了避免它們還需要配置環(huán)境,于是用 PyQt 寫了個界面,然后用 PyInstaller 打包成 exe 。打包過程中遇到了一些坑,紀(jì)錄一下。

PyQt

之前寫過一個蝦米歌單導(dǎo)出小腳本,exe 版本是用的 Python 自帶的 Tkinter 寫的,所以這次嘗試用 PyQt。寫的時候遇到了任務(wù)欄閃爍和打包后程序界面圖標(biāo)不顯示的問題。

  • 任務(wù)欄閃爍提示

    后臺運行程序的時候,如果使用 QFileDialog ,程序彈出保存對話框的時候會在任務(wù)欄閃爍提示。但不是每個 Widget 都會有這個功能,但是這時候可以通過 QtWidgetactivateWindow()QApplication.alert() 來實現(xiàn),但這兩者使用的時候會有點區(qū)別。

    activateWindow() 是實例方法,只要程序窗口切換到前臺被激活了就不會再閃爍。而 QApplication.alert(QWidget, msecs: int = 0) 是靜態(tài)方法,msecs 值為 0 的時候,和 activateWindow() 的效果一致,但是需要在閃爍停了之后激活程序才會任務(wù)欄窗口顏色才會恢復(fù)正常,否則還是黃色,直到閃爍停了之后再激活一次程序。msecs 不為 0 的時候,超過這個時間后,任務(wù)欄窗口就會自動恢復(fù)正常。所以 activateWindow() 是比較好的選擇,除非不要求一直在任務(wù)欄提示。

  • 資源文件在打包時的處理

    把代碼用 PyInstaller 打包到一個文件的時候,會出現(xiàn)圖標(biāo)或圖片都不顯示的情況。這種時候就需要用 Qt’s resource system 來對其進(jìn)行打包。

    首先新建一個 .qrc 文件,內(nèi)容格式如下:

    <RCC>
      <qresource prefix="/" >
        <file>img/image1.png</file>
        <file>img/image2.png</file>
        <file>img/image3.png</file>
      </qresource>
    </RCC>
    

    然后去文件目錄下執(zhí)行 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 打過包,但感覺不理想,搜索了下發(fā)現(xiàn) PyInstaller 用得比較多,就使用了這個,第一次用的時候沒遇到問題,但是因為 Python 是裝的 64 位的,所以打包之后的程序無法在 32 位的機(jī)器上使用。這就意味著我必須要在 Python 32 位的環(huán)境下打包,但重新配置了下環(huán)境之后,遇到了 ImportError 和無法鏈接到動態(tài)庫的問題。

  • ImportError: DLL load failed

    用 PyInstaller 給程序打包的時候遇到了pyi_rth_qt5plugins returned -1 的 Fatal Error 提醒。這個錯誤信息幾乎是毫無用處的,修改 .spec 文件,打開 debug 模式以及顯示 console 后,在 running pyi_rth_qt5plugins.py 的時候發(fā)生了 ImportError: DLL load failed 找不到指定的模塊 錯誤。

    回頭想起了在編譯的時候看到了很多 WARNNING 消息,回過頭查看,發(fā)現(xiàn)了很多 lib not found 的問題。但是仔細(xì)檢查了 Python 庫之后,這些 DLL 明明在 C:\Python35-32\Lib\site-packages\PyQt5\Qt\bin 目錄下,最后的搜索得到的解決辦法是把這個目錄添加到環(huán)境變量里。

    問題得到了解決,猜測原因是因為之前使用 pip 安裝 PyQt 的時候, pypi.python.org 總是連接不順暢,最后去下了個 .whl 文件直接安裝,導(dǎo)致沒有對應(yīng)環(huán)境變量打包的時候找不到 DLL。

    # 環(huán)境: 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 打包之后的程序運行的時候發(fā)生 api-ms-win-crt-runtime 動態(tài)庫之類的錯誤,似乎只有在 Python 3.5 下打包才會遇到。因為 Universal CRT (KB2999226)缺失,可以通過安裝此更新來解決問題?;蛘咧苯酉螺d Visual C++ Redistributable (x86 ,x64 )。

    參考鏈接:api-ms-win-crt-runtime-l1-1-0.dll is missing when open office file

這次的幾個坑讓我更堅定這類工具最好不要用最新版本,一不見得更穩(wě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)容