Creating an OSX PyQt app using Pyinstaller 2, PyQt4 and Qt5
Question: I am trying to package a PyQt program for OSX using PyInstaller 2, where PyQt4
(4.10) has been built against Qt 5.0.2 (from Git). The following simple
example doesn't work.

    
    
    import sys
    from PyQt4.QtGui import QApplication, QMessageBox
    
    def main():
        print "Hello"
        a = QApplication(sys.argv)
        m = QMessageBox(QMessageBox.Information, "Title", "Hello")
        m.exec_()
    
    if __name__=="__main__":
        main()
    

Spec file generated using pyinstaller-2.0/utils/MakeSpec.py and modified to
add the BUNDLE class.

    
    
    a = Analysis(['hello.py'],
             pathex=['/Users/glenn/rp/src/demo'],
             hiddenimports=[],
             hookspath=None)
    
    pyz = PYZ(a.pure)
    
    exe = EXE(pyz,
          a.scripts,
          exclude_binaries=1,
          name=os.path.join('build/pyi.darwin/hello', 'hello'),
          debug=False,
          strip=None,
          upx=True,
          console=False )
    
    coll = COLLECT(exe,
               a.binaries,
               a.zipfiles,
               a.datas,
               strip=None,
               upx=True,
               name=os.path.join('dist', 'hello'))
    
    app = BUNDLE(coll,
            name=os.path.join('dist', 'hello.app'),
            appname="Hello",
            version = '0.1'
            )
    

Packaging command

    
    
    > python pyinstaller.py --windowed hello.spec
    

Running the binary directly from the terminal gives this output before it
crashes:

    
    
    $ ./dist/hello.app/Contents/MacOS/hello 
    Hello
    Failed to load platform plugin "cocoa". Available platforms are: 
    
    Abort trap: 6
    

and this is the stack trace:

    
    
    Exception Type:  EXC_CRASH (SIGABRT)
    Exception Codes: 0x0000000000000000, 0x0000000000000000
    
    Application Specific Information:
    abort() called
    
    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0   libsystem_kernel.dylib          0x9a671a6a __pthread_kill + 10
    1   libsystem_c.dylib               0x93163b2f pthread_kill + 101
    2   libsystem_c.dylib               0x9319a4ec abort + 168
    3   QtCore                          0x03db156b qt_message_fatal(QtMsgType, QMessageLogContext const&, QString const&) + 11
    4   QtCore                          0x03db19df QMessageLogger::fatal(char const*, ...) const + 63
    5   QtGui                           0x068abceb QGuiApplicationPrivate::createPlatformIntegration() + 3547
    6   QtGui                           0x068abd16 QGuiApplicationPrivate::createEventDispatcher() + 38
    7   QtCore                          0x03f4f2c4 QCoreApplication::init() + 100
    8   QtCore                          0x03f4f23b QCoreApplication::QCoreApplication(QCoreApplicationPrivate&) + 59
    9   QtGui                           0x068aa0d0 QGuiApplication::QGuiApplication(QGuiApplicationPrivate&) + 32
    10  QtWidgets                       0x06c695de QApplication::QApplication(int&, char**, int) + 238
    11  PyQt4.QtGui.so                  0x06394454 init_QApplication + 196
    12  sip.so                          0x007bc7d5 sipSimpleWrapper_init + 266
    13  Python                          0x0385c174 type_call + 340
    14  Python                          0x0380d401 PyObject_Call + 97
    15  Python                          0x0389c093 PyEval_EvalFrameEx + 10131
    16  Python                          0x038a0490 fast_function + 192
    17  Python                          0x0389beae PyEval_EvalFrameEx + 9646
    18  Python                          0x038998b2 PyEval_EvalCodeEx + 1922
    19  Python                          0x03899127 PyEval_EvalCode + 87
    20  Python                          0x038be06e PyRun_StringFlags + 126
    21  Python                          0x038bdfb1 PyRun_SimpleStringFlags + 81
    22  Python                          0x038bf619 PyRun_SimpleString + 25
    23  hello                           0x00003240 runScripts + 240
    24  hello                           0x0000280a main + 442
    25  hello                           0x00001eb9 _start + 224
    26  hello                           0x00001dd8 start + 40
    

The issue appears to be that it can't find the libqcocoa.dylib plugin. This is
not surprising as it is not packaged. Is that the actual issue here and do I
need to include this plugin? If so where does it need to go? I have tried
putting it in demo.app/Contents/plugins but that doesn't help.


Answer: The right place to put libqcocoa.dylib is in
`Contents/MacOS/qt4_plugins/platforms`:

    
    
    extralibs = [("qt4_plugins/platforms/libqcocoa.dylib", "/path/to/libqcocoa.dylib", "BINARY")
                 ]
    coll = COLLECT(exe,
                   a.binaries + extralibs,
                   a.zipfiles,
                   a.datas,
                   strip=None,
                   upx=False,
                   name=os.path.join('dist', 'hello'))
    

The app now starts but the dialog window never appears. Edit: This is because
PyInstaller (v 2.0) adds LSBackgroundOnly=true to the apps Info.plist.
Removing this allows the window to show.

