此应用程序无法启动,因为它无法找到或加载Qt平台插件" cocoa"

时间:2014-08-07 16:58:49

标签: macos python-3.x bundle cx-freeze pyqt5

我想我在过去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

问题是我觉得很明显:我做错了什么? (或者我不做什么?)

4 个答案:

答案 0 :(得分:6)

在MacOSX上使用cx_Freeze构建应用时,所有相关库(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

结果One of the two will be used. Which one is undefined.表示可以加载其中任何一个。如果它选择了正确的那个,太好了!如果它没有同时加载两组独立的库,那么很快就会失败。顺便说一句,你可能会发现如果你在另一个系统上试用你的应用程序它会工作正常! 有时

有关问题的概述,我建议您查看以下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

每个库文件都包含其依赖关系的路径。如果您收到此错误,则表示其中一些路径要么a)仍然指向原始文件,要么b)不够具体(并且在PATHDYLD_LIBRARY_PATH上找到)。但是,您可以从命令行使用install_name_tool重新编写路径(如上所述here

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) 
...

updated workaround in the issue tracker表示只需在您的应用中导入正确的模块即可使其正常运行,但您似乎不太可能在没有QtWidgets的情况下创建应用程序。

选项2

如果上述方法无效,则可以采用另一种方法here。这是一个大锤的方法,它只是简单地防止加载插件。

  • 在可执行文件旁边添加qt.conf文件(在.app包中,其中包含:
    [Paths] Plugins = '.'

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

    < / LI>

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

答案 1 :(得分:2)

这是@ mfitzp的回答。

QT Plugins Document派上用场了。

要查找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的答案)那里,我的应用程序工作喜欢魅力。

BTW建议MAC codesigning guide正确设置此目录结构,

DONT将框架,插件放在ncher.app/Contents/MacOS目录

答案 2 :(得分:2)

使用此命令:

pip install opencv-python-headless

它解决了我的情况。

答案 3 :(得分:0)

我在刚刚从Qt Creator启动Qt Widgets应用程序的环境中遇到了这个问题。

帮助我的是将变量QT_PLUGIN_PATH设置为值<Qt-dir>/plugins(其中<Qt-dir>是Qt目录中文件夹的绝对路径,其中包含{{1} },bindocinclude,当然还有lib)。

这可能无法解决问题的根本原因,但这是一个快速解决方案,到目前为止工作正常。