我的PyInstaller规范:
# -*- mode: python -*-
block_cipher = None
a = Analysis(['test.py'],
pathex=['C:\\Users\\admin\\compile'],
binaries=[('C:\\Python361\\Lib\\site-packages\\PyQt5\\Qt\\plugins\\platforms\\qwindows.dll', 'qwindows.dll')],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
name='test',
debug=False,
strip=False,
upx=False,
runtime_tmpdir=None,
console=False , icon='icon.ico')
所以我遇到了一个问题,我将使用pip的最新版PyInstaller编译我的PyQt5 5.8.2(使用Python 3.6.1)程序,它可以工作!静态链接的onefile可执行文件在我的计算机上运行,其中包含所有Qt内容。
但是我在没有设置Qt环境的任何计算机或虚拟机上测试它,并且因为"无法找到或加载Qt平台插件而在启动时崩溃#39;窗户'"错误。如果您查看规范,您会注意到我尝试手动将DLL存储在二进制列表中,因此PyInstaller会将其存储在可执行文件中,但这并不起作用。
我想知道我需要更改什么,以便我可以编译我的应用程序,而不必像在可执行文件夹中包含platforms文件夹那样(我希望所有内容都在可执行文件中),是不是就像我没有意识到的spec文件中的更改一样简单,以便将DLL存储在可执行文件中?
顺便说一下,这不是重复的。我查看了其他一些问题,所有这些问题都是针对不同类型的应用程序,或者解决方法是将DLL降级或存储在文件夹中,我无法执行其中任何一项。
编辑:所以我把它更改为onedir只是为了看看它是否在那里,并且qwindows.dll在文件夹内。还有一个qt5_plugins文件夹,它有一个平台文件夹,也有一个qwindows.dll。那怎么没有检测到dll ??答案 0 :(得分:2)
似乎有两种解决方案,第一种解决方案适合我:
将平台目录复制到可执行文件的目录中。您可以在c:\Users\<username>\envs\<environmentname>\Library\plugins\platforms
或
升级到较新版本的pyqt:conda install -c anaconda pyqt
谨慎使用第二个选项:如果您有conda环境,请不要尝试使用pip进行pyqt安装,这可能会破坏您的conda安装: https://github.com/ContinuumIO/anaconda-issues/issues/1970
答案 1 :(得分:1)
我只是将我的pyqt5软件包更新到5.10.1并修复它。
答案 2 :(得分:1)
在 PyQt6 6.0.3 和 PyInstaller 4.3 上遇到同样的问题。
首先尝试了一个单文件夹包,在将平台和样式插件添加到 binaries
列表并将 PyQt6.sip
添加到 hiddenimports
后运行良好(后者可能只需要如果使用 PyQt6)。
当我尝试单文件包时,我收到了平台插件错误。首先,我通过查看运行时解压缩包的临时文件夹(打开错误对话框)检查文件是否被复制,并且所有 DLL 都在那里。当我复制到与可执行文件相同的文件夹时,它工作正常,问题是 Qt 没有在临时文件夹中找到它们。
我在 Qt documentation 中找到了有关 QT_PLUGIN_PATH
的解决方案,然后在此 PyInstaller commit 中查找。
添加插件的 DLL 后,只需添加一个运行时挂钩来设置 QT_PLUGIN_PATH
。
此外,如果使用 UPX,插件的 DLL 需要添加到 upx_exclude
列表中。
这是我使用的钩子和规范文件,删除了默认选项:
import os
import sys
from pathlib import Path
os.environ['QT_PLUGIN_PATH'] = str( Path( sys._MEIPASS ) / 'PyQt6/Qt6' )
from pathlib import Path
root = Path.cwd()
qtRoot = root / 'env/Lib/site-packages/PyQt6/Qt6'
analysis = Analysis(
scripts = [
root / 'src/main.py',
],
pathex = [
root,
qtRoot / 'bin',
],
binaries = [
( qtRoot / 'plugins/platforms/qwindows.dll', 'PyQt6/Qt6/plugins/platforms' ),
( qtRoot / 'plugins/styles/qwindowsvistastyle.dll', 'PyQt6/Qt6/plugins/styles' ),
],
hiddenimports =[
'PyQt6.sip',
],
runtime_hooks = [
'pyQtHook.py',
],
)
pyz = PYZ( analysis.pure, analysis.zipped_data )
exe = EXE(
pyz,
analysis.scripts,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
name = 'MyApp',
console = False,
upx = True,
upx_exclude = [
'qwindows.dll',
'qwindowsvistastyle.dll',
],
)
答案 3 :(得分:0)
我有一个问题,我的python代码可以正常工作,但是编译的.exe文件将提供“找不到或加载Qt平台插件窗口”的问题。通过将使用~PyQt5\Qt\plugins\platforms
生成的程序目录中的pyinstaller --onedir main.py
文件夹复制到包含.exe文件的文件夹中,我们解决了该问题。
在我看来,“帮助”程序检测所需.dll的唯一方法是在platforms
旁边放置main.exe
文件夹。使用platforms
后将pyinstaller --onefile main.py
文件夹粘贴到程序的目录中也会使程序正常工作。
答案 4 :(得分:0)
这是一个古老的问题,但是几天来我一直在寻找解决方案,我终于设法解决了该问题,而无需手动复制文件夹。
由于此问题也使用.spec
文件,因此我认为这是正确的位置。
这个想法是.exe
在路径.dll
中寻找./platforms/*.dll
,因此我只是将所有dll添加到spec文件中的binaries数组中,它们的路径位于束是platforms/*.dll
。这是因为binaries
是一个元组数组,其中第一个值是文件的路径,第二个值是bundle中的路径(几乎是.exe“容器”内部的路径)。>
除此之外,我认为最上面的状态mode: python
表示它是作为python脚本执行的,因此它应支持变量,字符串和串联。所以我的规格文件最终看起来像这样:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
pf_foldr='C:\\Users\\Gabryxx7\\anaconda3\\envs\\<env_name>\\Library\\plugins\\platforms\\'
a = Analysis(['C:\\Users\\Gabryxx7\\PycharmProjects\\<proj_name>\\program.py'],
pathex=['C:\\Users\\Gabryxx7\\PycharmProjects\\<proj_name>\\'],
binaries=[(pf_foldr+'qwindows.dll', 'platforms\\qwindows.dll'),
(pf_foldr+'qdirect2d.dll', 'platforms\\qdirect.dll'),
(pf_foldr+'qoffscreen.dll', 'platforms\\qoffscreen.dll'),
(pf_foldr+'qwebgl.dll', 'platforms\\qwebgl.dll')
],
datas=[],
hiddenimports=['GUI', 'API', 'Threading', 'ssl', 'pyodbc'],
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='programName',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True ) # False to avoid the console
我以前曾尝试过在网上找到的每个解决方案:设置环境变量QT_QPA_PLATFORM_PLUGIN_PATH
,重新安装Anaconda,更新所有软件包,使用PyPi版本且没有venvs尝试,但没有任何效果。最后,使用platforms
复制dlls
文件夹可以达到目的,编辑规范文件也可以避免手动操作。
答案 5 :(得分:0)
在试图解决这个问题时,我的大脑几乎要爆炸了,我想出了一个对我有用的解决方案。
在 SPEC 文件中我添加了子句:upx_exclude=['qwindows.dll'],
事实证明,在 PyInstaller 冻结过程中压缩时,此 DLL 已损坏。将 DLL 添加到 upx_exclude
子句可以防止出现此问题。
您可以在此处查看我的 SPEC 文件的一部分:
...
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='Hydro Tax Automation App',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=['qwindows.dll'],
runtime_tmpdir=None,
console=False)