以上省略pyinstaller安裝步驟,直入主題。先分享我的心路歷程。
1.pyinstaller -F -i 1.ico UI_Main.py (先在CMD中 cd到 py文件對應的路徑)
第一步打包成功,打開EXE,界面正常顯示,但是連不上項目的IC板。故看到打包時的warning,懷疑是受此影響,幾經輾轉查閱,發現所缺的dll都是QT的dll,這里的QT指的是C++版的QT,於是我專程去官網下載安裝了一個QT。
於是將所缺的dll如數轉移到我的 UI_Main.py的同一根目錄下:
2. 再次 pyinstaller -F -i 1.ico UI_Main.py
此時 warning: lib not found 已無,打包完成,再次打開EXE,本人的UI還是無法連結到IC板,而在pycharm工程程序中卻是完美運行。這驗證說明這些Qt53xx文件是無害的。
3.查閱論壇,很多文章說到pyinstaller 打包時,導入路徑的問題,我整理了些許方法,並進行了驗證:
(1).主函數 import xx 導入模塊,可免去其他形式導入【這里解決:pyinstaller打包后,打開報錯:not find xx module】
(2). pyinstaller -F -i 1.ico UI_Main.py -p 路徑/文件【主要解決:import 引發的路徑查找不到的問題】
(3).UI_Main.spec文件中 pathex=[],binaries=[],datas=[] 分別添加需要額外添加的導入路徑,額外添加的二進制文件,額外添加的數據文件。注意,spec文件搭配的CMD指令是 pyinstaller --clean -F UI_Main.spec -i 1.ico 【--clean是清除pyinstaller 緩存文件,這里如果后接UI_Main.py則會使 spec文件被刷新,所以接的是 UI_Main.spec】
(4).CMD: pyinstaller -F -i 1.ico UI_Main.py --add-datas=xxx.dll;. 【其實與(3)中添加datas=[]是一樣的效果】
(5).主函數添加相應的路徑 sys.path.append() 【其實也是和(1)差不多,能添加打包的搜索路徑。】
以下是 spec文件的全內容,datas=[]中的"."表示將該文件復制到根路徑(UI_Main.py同),並從根路徑搜索,添加到打包內容。
# -*- mode: python ; coding: utf-8 -*- block_cipher = None a = Analysis(['UI_Main.py'], pathex=['D:\\PyQt\\module\\AxpSys_DEBUG\\axp\\drivers', 'C:\\Python36\\Lib', 'D:\\PyQt'], binaries=[], datas=[('xxx1.dll', "."), ('xxx2.dll', "."), ('xxx3.csv', ".")], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=block_cipher, noarchive=False) pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='UI_Main', debug=False, bootloader_ignore_signals=False, strip=False, upx=True, upx_exclude=[], runtime_tmpdir=None, console=False , icon='1.ico')
4.我將這4種方法都試過,確實能解決相應問題,應該也能解決普遍問題。
但仍未能解決我的UI不能連結IC板卡的問題。於是我思考一下,想到windows連結IC卡時,我是有安裝過基於通訊的驅動,那懷疑堅定加肯定一定是,驅動部分的相關文件沒有被打包進去。於是,我獨立寫了一個簡單demo,對IC進行通訊的實驗,並進行了每一個步驟的print偵測。驚奇的發現成功了!
這里demo已經連上了IC板卡(也就是單片機啦啦啦),然后我葫蘆畫瓢,在UI_Main.py上造車,一樣的輪子,竟然還是不行!
我努力對照spec 文件發現一模一樣,也是根據 pyinstaller --clean -F UI_Main.spec -i 1.ico 相同的指令。我仔細反復查找,終於找到了兩者唯一的不同!!!二者唯一不用的是 spec文件中 xxx1.dll 與 xxx2.dll的順序是相反的【也就是一個1,2,3;另一個2,1,3】,我懷揣着忐忑試探着最后那一絲不似希望的希望。
最后終於成功了!!!原理驅動裝載的順序也是影響最后IC讀寫的,我猜測是因為xxx2.dll 中有調用到 xxx1.dll的函數,但是因為我放的順序是datas=[('xxx2.dll', '.'), ('xxx1.dll','.'), ('xxx3.csv','.')] 導致系統pyinstaller 先導入的xxx2.dll 因為引用不到 xxx1.dll中的函數,而在打包的時候直接報錯,當我把順序調整之后,才能完美運行!
總結,關於程序需要額外加載的dll 文件【比如:上文提到的Qt53xx.dll此類與程序相關的,皆為內部導入,非額外】,額外具體指的是,在python 程序中使用到的WinDLL等,相關windows驅動時,可視為額外加載dll。
impor ctypes ctypes.WinDLL('xxx1.dll') ctypes.CDLL(path,'xxx2.dll')
故,我這里因為是和單片機通訊,需要加載額外dll,所以會遇到這個問題,希望和我遇到類似問題與坑的同鞋們看到這篇文章與有此受益,感謝閱讀,請不要憐惜自己給我點個贊吧。
歡迎評論交流 pyinstaller 等的相關問題。
補充一點:我的驗證demo是在虛擬環境pipenv中驗證的,其實pyinstaller網上的文章大部分是可以借鑒的,只是指令不同而使用時有所誤導而已。