这个应用程序启动失败,因为它找不到或加载不了Qt平台插件“cocoa”。

37

我觉得在过去的20个小时里我已经尽力了,但好像什么都不起作用。我的应用程序正在运行并且工作正常 - 就像应该的那样 - 我唯一的问题是无法从中创建一个 .app 包。我尝试了 Py2Appcx_Freeze,但它们都没有起作用。因为需要支持多平台,如果可能的话,我会坚持使用后者。

setup.py 看起来像这样:

import sys
from cx_Freeze import setup, Executable

base = None
if sys.platform == 'win32':
    base = 'Win32GUI'

OPTIONS = {'build_exe': {'includes': ['sip',
                                      'PyQt5',
                                      'PyQt5.QtCore',
                                      'PyQt5.QtGui',
                                      'PyQt5.QtWidgets',
                                      'PyQt5.QtMultimediaWidgets',
                                      'PyQt5.QtMultimedia',
                                      'PyQt5.QtNetwork']}}

EXECUTABLES = [Executable('main.py', base=base)]
NAME = 'coublet'
VERSION = '0.5.70'

setup(name = NAME,
      version = VERSION,
      options = OPTIONS,
      executables = EXECUTABLES)

我收到的错误信息是:

objc[28404]: Class NotificationReceiver is implemented in both
/Users/.../build/coublet-0.5.70.app/Contents/MacOS/QtWidgets and
/usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets. One of
the two will be used. Which one is undefined.
QObject::moveToThread: Current thread (0x7fc4b96e98b0) is not the object's thread
(0x7fc4b95dbc80).
Cannot move to target thread (0x7fc4b96e98b0)

On Mac OS X, you might be loading two sets of Qt binaries into the same process.
Check that all plugins are compiled against the right Qt binaries. Export
DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.
This application failed to start because it could not find or load the Qt
platform plugin "cocoa".

Available platform plugins are: cocoa, minimal, offscreen.

Reinstalling the application may fix this problem.
Abort trap: 6

我的系统信息:

Mac OS X  : 10.9.4
Python    :  3.4.1
cx_Freeze :  0.9
PyQt5:    :  5.3.1
- - -
Packages installed via: Homebrew and PIP

.app 结构:

build/coublet-0.5.70.app
└── Contents
    ├── Frameworks
    ├── Info.plist
    ├── MacOS
    │   ├── PyQt5.QtCore.so
    │   ├── PyQt5.QtGui.so
    │   ├── PyQt5.QtMultimedia.so
    │   ├── PyQt5.QtMultimediaWidgets.so
    │   ├── PyQt5.QtNetwork.so
    │   ├── PyQt5.QtWidgets.so
    │   ├── Python
    │   ├── QtCore
    │   ├── QtCore.so
    │   ├── QtGui
    │   ├── QtGui.so
    │   ├── QtMultimedia
    │   ├── QtMultimedia.so
    │   ├── QtMultimediaWidgets
    │   ├── QtMultimediaWidgets.so
    │   ├── QtNetwork
    │   ├── QtNetwork.so
    │   ├── QtOpenGL
    │   ├── QtWidgets
    │   ├── QtWidgets.so
    │   ├── _bisect.so
    │   ├── _bz2.so
    │   ├── _codecs_cn.so
    │   ├── _codecs_hk.so
    │   ├── _codecs_iso2022.so
    │   ├── _codecs_jp.so
    │   ├── _codecs_kr.so
    │   ├── _codecs_tw.so
    │   ├── _datetime.so
    │   ├── _hashlib.so
    │   ├── _heapq.so
    │   ├── _json.so
    │   ├── _lzma.so
    │   ├── _md5.so
    │   ├── _multibytecodec.so
    │   ├── _opcode.so
    │   ├── _pickle.so
    │   ├── _posixsubprocess.so
    │   ├── _random.so
    │   ├── _scproxy.so
    │   ├── _sha1.so
    │   ├── _sha256.so
    │   ├── _sha512.so
    │   ├── _socket.so
    │   ├── _ssl.so
    │   ├── _struct.so
    │   ├── array.so
    │   ├── binascii.so
    │   ├── grp.so
    │   ├── imageformats
    │   │   ├── libqdds.dylib
    │   │   ├── libqgif.dylib
    │   │   ├── libqicns.dylib
    │   │   ├── libqico.dylib
    │   │   ├── libqjp2.dylib
    │   │   ├── libqjpeg.dylib
    │   │   ├── libqmng.dylib
    │   │   ├── libqsvg.dylib
    │   │   ├── libqtga.dylib
    │   │   ├── libqtiff.dylib
    │   │   ├── libqwbmp.dylib
    │   │   └── libqwebp.dylib
    │   ├── libcrypto.1.0.0.dylib
    │   ├── liblzma.5.dylib
    │   ├── library.zip
    │   ├── libreadline.6.dylib
    │   ├── libssl.1.0.0.dylib
    │   ├── main
    │   ├── math.so
    │   ├── platforms
    │   │   ├── libqcocoa.dylib
    │   │   ├── libqminimal.dylib
    │   │   └── libqoffscreen.dylib
    │   ├── pyexpat.so
    │   ├── readline.so
    │   ├── select.so
    │   ├── sip.so
    │   ├── termios.so
    │   ├── time.so
    │   ├── unicodedata.so
    │   └── zlib.so
    └── Resources

问题很明显:我做错了什么?(或者我没有做什么?)


只是一个建议:您可以暂时删除 /usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets(例如通过重命名或通过 homebrew 删除)。这应该让您成功构建应用程序包。 - Anthony Kong
我在Windows上也遇到了同样的问题。我必须自己将libEGL.dll添加到主应用程序目录中。那么在OS X上可能有类似的动态库吗? - Fenikso
4个回答

7
使用cx_Freeze在MacOSX上构建应用程序时,所有依赖的库(MacOSX上的.so文件)都被打包到应用程序包中。这使得应用程序可以在其他系统上进行移植,而无需安装Qt的第二个副本。
启动应用程序时,库应从应用程序包内部加载。但是,在您的情况下,系统库仍然被加载:
/Users/.../build/coublet-0.5.70.app/Contents/MacOS/QtWidgets
/usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets

结果其中之一将被使用。哪一个未定义。的意思是这两者中的任何一个都可以被加载。如果它选择了正确的一个,那太好了!如果它没有,你就会有两组不同的库同时加载,然后很快失败。另外,你可能会发现,如果你在另一个系统上尝试你的应用程序,它会正常工作!有时候

为了概述问题,我建议查看以下bug #33

开始之前

确保你安装了最新版本的cx_Freeze。我建议尝试克隆存储库并从那里安装。

其次,确保Qt插件被正确地构建到您的应用程序中。Cx_Freeze以前会查找qt-menu.nib文件来确定它是否正在构建一个Qt应用程序。在Qt5中不再可用,但是您可以在构建应用程序时通过命令行传递它。将其设置为任何您想要的内容即可,这并不重要:
python setup.py bdist_mac --qt-menu-nib=/usr/local/Cellar/qt5/5.3.1/plugins/platforms/

这可能足以解决您的问题。但如果不行,您有两个选择:

选项1

每个库文件都包含其依赖项的路径。如果您收到此错误消息,则意味着其中一些路径要么仍指向原始文件,要么不够具体(并且在您的PATHDYLD_LIBRARY_PATH中找到)。然而,您可以使用命令行中的install_name_tool重新编写路径(如此处所述):

install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/QtWidgets build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtCore.framework/Versions/5/QtCore @executable_path/QtCore build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtPrintSupport.framework/Versions/5/QtPrintSupport @executable_path/QtPrintSupport build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib
install_name_tool -change /usr/local/Cellar/qt5/5.3.1/lib/QtGui.framework/Versions/5/QtGui @executable_path/QtGui build/MyApp.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib

这将重新编写库中的路径,以指向您的应用程序文件夹,并以@executable_path为基础。您需要对所有加载不正确的路径执行此操作。我建议将其包装到一个脚本中,在构建后自动运行。
如果您想查看文件引用的库,可以使用otool。例如,在我的成功构建的应用程序中:
otool -L libqcocoa.dylib 
libqcocoa.dylib:
    @executable_path/../Resources/qt_plugins/platforms/libqcocoa.dylib (compatibility version 0.0.0, current version 0.0.0)
    /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 20.0.0) 
...

在问题跟踪器中有一个更新的解决方法建议只需将正确的模块导入您的应用程序即可使其正常工作,但是似乎不太可能您没有使用 QtWidgets 创建应用程序。

选项2

如果以上方法不起作用,则可以尝试另一种方法,该方法在此处进行了说明。这有点像狠狠地敲打,因为它根本禁止了加载插件。

  • 在可执行文件旁边添加一个qt.conf文件(在包含以下内容的.app包中:
    [Paths] Plugins = '.'

  • 在导入 PyQt 之前,在应用程序中设置环境变量QT_PLUGIN_PATH=""。或者在创建应用程序对象之前调用QtGui.QApplication.setLibraryPaths([])

结果是没有插件,因此您的应用程序将无法访问MacOSX Cocoa样式和UI(例如文件、颜色对话框)。

很棒的答案。 请您看一下这个问题:https://stackoverflow.com/questions/45858376/creating-dmg-for-qt-app-mac-osx - arqam
文件路径:dist/fullmain.app/Contents/MacOS/qt_plugins/platforms/libqcocoa.dylib(找不到该文件或目录) - USERNAME GOES HERE

5

使用以下命令:

pip install opencv-python-headless

它解决了我遇到的同样问题。

2
这是对 @mfitzp 的回答的补充。
这个 QT 插件文档 很有用。
要查找 QT 应用程序正在尝试搜索的默认位置,您可以使用以下命令:
$sudo dtruss MacOS/ncher 
  getattrlist("/ncher.app\0", 0x7FFF954B51A4, 0x7FFF5C8FDD20)              = 0 0
  getattrlist("/ncher.app/Contents\0", 0x7FFF954B51A4, 0x7FFF5C8FDD20)             = 0 0
  getattrlist("/ncher.app/Contents/MacOS\0", 0x7FFF954B51A4, 0x7FFF5C8FDD20)               = 0 0
  stat64("/ncher.app/Contents/MacOS\0", 0x7FFF5C8FDED8, 0x7FFF5C8FDD20)            = 0 0
  stat64("/ncher.app/Contents/MacOS/platforms/.\0", 0x7FFF5C8FDF58, 0x7FFF5C8FDD20)                = -1 Err#2
  open("/dev/tty\0", 0x1000000, 0x1FF)             = 5 0
  fcntl(0x5, 0x2, 0x1)             = 0 0
  close(0x5)               = 0 0
  write_nocancel(0x2, "This application failed to start because it could not find or load the Qt platform plugin \"cocoa\".\n\nReinstalling the application may fix this problem.\n\0", 0x97)              = 151 0
  sigprocmask(0x3, 0x7FFF5C8FE6B4, 0x0)            = 0x0 0
  __pthread_sigmask(0x3, 0x7FFF5C8FE6C0, 0x0)              = 0 0
  __pthread_kill(0x603, 0x6, 0x0)          = 0 0
  kevent64(0x4, 0x0, 0x0)          = -1 Err#4

你可以看到这个QT应用程序试图查找MacOS/platforms,一旦我将我的libqcocoa.dylib插件复制到那里(它的路径被install_name_tool命令修改,如@mfitzp的答案所述),我的应用程序就像魔术般工作了。
顺便说一下,MAC codesigning guide建议正确设置此目录结构,不要将框架和插件放在ncher.app/Contents/MacOS目录中。

非常感谢!你的链接真的帮了我大忙! - Aman
请问您能否查看一下这个问题:https://stackoverflow.com/questions/45858376/creating-dmg-for-qt-app-mac-osx - arqam

0

我在从Qt Creator启动Qt Widgets应用程序时遇到了这个问题。

帮助我的是将变量QT_PLUGIN_PATH设置为值<Qt-dir>/plugins(其中<Qt-dir>是包含bindocincludelib和当然plugins等文件夹的Qt目录中的绝对路径)。

这可能没有修复问题的根本原因,但它是一个快速解决方案,目前运行良好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接