pyinstaller打包exe文件閃退的解決辦法


  pyinstaller是python下目前能打包py文件為windows下的exe文件的一個非常友好易用的庫!但是,小爬每次用pyinstaller打包時也總是遇到一些難題,有時網上搜了一圈,也沒看到合適的答案。小爬因此決定把我的問題和后來的解決思路都寫出來,供后來者參考!

  事情是這樣的,小爬最近編寫了一個發票PDF文件的識別腳本:1、用到PyMuPDF中的fitz模塊來提取發票的二維碼圖片元素;2、用到pyzbar來提取二維碼信息;3、用pdfplumber(該庫依賴於pdfminer.six庫)來提取PDF文件中的文本和表格數據;4、用Pillow庫對處理圖像對象。

  腳本寫完后,可以正常地在Visual Studio Code下跑出結果,符合預期。用pyinstaller打包為單個exe文件的過程看上去很“完美”,但是封裝后的exe文件每次執行都閃退,錯誤信息如下:

Traceback (most recent call last):
  File "lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py", line 149, in __init__
  File "ctypes\__init__.py", line 348, in __init__
OSError: [WinError 126] 找不到指定的模塊。

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "lib\site-packages\pyzbar\zbar_library.py", line 58, in load
  File "lib\site-packages\pyzbar\zbar_library.py", line 52, in load_objects
  File "lib\site-packages\pyzbar\zbar_library.py", line 52, in <listcomp>
  File "ctypes\__init__.py", line 426, in LoadLibrary
  File "lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py", line 151, in __init__
__main__.PyInstallerImportError: Failed to load dynlib/dll 'libiconv.dll'. Most probably this dynlib/dll was not found when the application was frozen.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py", line 149, in __init__
  File "ctypes\__init__.py", line 348, in __init__
OSError: [WinError 126] 找不到指定的模塊。

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "tel_Fee_Invoice_Info_Extract.py", line 13, in <module>
    import pyzbar.pyzbar as pyzbar
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "d:\settlement_env\venv\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "lib\site-packages\pyzbar\pyzbar.py", line 7, in <module>
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "d:\settlement_env\venv\lib\site-packages\PyInstaller\loader\pyimod03_importers.py", line 627, in exec_module
    exec(bytecode, module.__dict__)
  File "lib\site-packages\pyzbar\wrapper.py", line 143, in <module>
  File "lib\site-packages\pyzbar\wrapper.py", line 136, in zbar_function
  File "lib\site-packages\pyzbar\wrapper.py", line 115, in load_libzbar
  File "lib\site-packages\pyzbar\zbar_library.py", line 60, in load
  File "lib\site-packages\pyzbar\zbar_library.py", line 52, in load_objects
  File "lib\site-packages\pyzbar\zbar_library.py", line 52, in <listcomp>
  File "ctypes\__init__.py", line 426, in LoadLibrary
  File "lib\site-packages\PyInstaller\loader\pyiboot01_bootstrap.py", line 151, in __init__
__main__.PyInstallerImportError: Failed to load dynlib/dll 'C:\\Users\\newjune\\AppData\\Local\\Temp\\_MEI164962\\pyzbar\\libiconv.dll'. Most probably this dynlib/dll was not found when the application was frozen.
[18280] Failed to execute script tel_Fee_Invoice_Info_Extract

  該traceback看是在說 缺少"ctypes\__init__.py" 模塊,實際上,經過它的提示,我們能在對應的路徑下找到該模塊,並不能發現什么異常。這段報錯信息的倒數第二行

Failed to load dynlib/dll 'C:\\Users\\newjune\\AppData\\Local\\Temp\\_MEI164962\\pyzbar\\libiconv.dll'. Most probably this dynlib/dll was not found when the application was frozen.

,似乎在暗示該exe文件,每次執行的時候,會在計算機本地的Temp文件下生成一個臨時文件夾,其中,要調用的動態鏈接庫文件”libiconv.dll“找不到,改庫是二維碼解析庫 pyzbar要運行的必要依賴文件。

我們在venv的虛擬環境下對應的文件夾”\venv\Lib\site-packages\pyzbar“ 下可以找到它:

 

   小爬這次決定試試pyinstaller的打包為文件夾功能,不再打包為單個exe文件:使用pyinstaller -D your.py 語句即可。果不其然,該方法下打包也很順利,但是生成的文件夾下,我們可以看到很多的依賴文件和pyd文件。

 

 

  最重要的一點,對應的exe文件執行時候報錯跟上面的traceback錯誤信息是一樣的。這個生成的文件夾下已經包含了諸多的windows下需要的dll文件,但是並沒有我們要的”pyzbar\\libiconv.dll",小爬決定將上文找到的文件夾整個復制到該工具目錄下。再次運行,此時程序可以正常運行,但是在提取pdf文件的文本信息時,濾掉了所有的中文字符,只能顯示字母、數字和特殊符號。小爬馬上聯想到,這是缺少PDF中文字符的解碼包。聯想到 我使用的pdfplumber 庫是基於 pdfminer.six庫 二次開發。我們再次找到 pdfminer.six所在的文件夾:

 

 

 

該子文件夾”cmap“中存儲着大量的PDF字符解碼包:

 

 

  小爬猜想這就是我們程序需要的,pyinstaller在打包的過程中再次漏掉了引用這些解碼包。小爬再次將整個pdfminer文件夾拷貝到 程序的根目錄下,這次,再次運行exe文件,已經可以完美執行,大功告成。小爬猜想,pyinstaller只是沒有成功封裝 這些第三方依賴文件,但是py文件應該已經封裝過。為此,小爬刪除了pdfminer文件夾和pyzbar文件夾下的所有py文件,再次運行工具,依舊完美執行!

  照理說,此時,該工具已經達到了預期的目的,但是小爬還是想把整個含exe核心文件的文件夾打包成一個單獨的exe可執行文件,有沒有辦法做到呢?辦法當然有,我們需要用到 ”Enigma Virtual Box“該文件。它能幫我們很方便的實現該功能:

 

   注意事項就一點:該工具支持直接將我們的目錄拖拽到virtual box Files 樹內,一鍵生成目錄樹,不需要手工創建節點!

  至此,大功告成,如果您也遇到和小爬一樣的pyinstaller打包問題,不妨參照上面的方法試一試!

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM