此应用程序无法启动,因为它无法find或加载Qt平台插件“cocoa”

我想在过去的20个小时里我尽了一切努力,但似乎没有任何效果。 我的应用程序正在运行并正在运行 – 就像它应该一样 – 我唯一的问题是我无法从它创build一个.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 

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

在MacOSX上使用cx_Freeze构build应用程序时,所有相关库(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. One of the two will be used. Which one is undefined. 意味着其中任何一个都可以被加载。 如果它select正确的,太棒了! 如果不是,你有两套独立的库同时加载,并在不久之后失败。 顺便说一下,你可能会发现,如果你在另一个系统上尝试你的应用程序,它将正常工作! 有时候

有关这个问题的概述,我build议看看下面的错误#33 。

在你开始之前

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

其次,确保Qt插件被正确地构build到您的应用程序中。 Cx_Freeze先前查找了qt-menu.nib文件以确定它是否构build了一个Qt应用程序。 这在Qt5中不再可用,但是在构build应用程序时,您可以在命令行上传递它。 将其设置为任何你想要的,这真的没有关系:

 python setup.py bdist_mac --qt-menu-nib=/usr/local/Cellar/qt5/5.3.1/plugins/platforms/ 

这可能足以解决您的问题。 但是,如果没有,你有两个select:

选项1

每个库文件都包含它的依赖path。 如果您收到此错误,则表示这些path中的一部分或者a)仍指向原始文件,或者b)不够详细(并且在您的PATHDYLD_LIBRARY_PATH )。 但是,您可以使用install_name_tool从命令行重新编写path(如下所述:

 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 

这将重写库中的path,以@executable_path作为基础,将其指向您的应用程序文件夹。 您将需要为所有发现加载不正确的path执行此操作。 我build议把它包装到一个脚本中,在构build之后自动运行。

如果你想看一个文件引用哪个库,你可以使用otool 。 例如,在我的一个成功构build的应用程序中:

 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情况下创build应用程序。

选项2

如果上述不起作用,这里还有另一种方法。 这是一个大锤的方法,它只是防止加载插件。

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

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

结果是没有插件,所以你的应用程序将无法访问MacOSX Cocoa风格和UI(例如文件,颜色对话框)。

这是@ mfitzp的答案。

这个QT插件文件派上用场。

要查找您的QT应用正在尝试search的默认位置,可以使用以下命令:

 $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插件(它的path被修改install_name_tool命令根据@ mfitzp的答案)在那里,我的应用程序工作就像魅力。

顺便说一句, MAC代码指导build议正确设置这个目录结构,

不要把框架,插件在ncher.app/Contents/MacOS目录