Не удалось создать отдельное приложение python/Qt с помощью cx_freeze (или Py2App) на Mac

У меня возникли проблемы с созданием отдельного приложения для Mac из программы на основе Python Qt как при использовании cx_freeze, так и при использовании Py2App. (обратите внимание, что я успешно сделал это в Windows с помощью cx_freeze).

На самом деле пример 'PyQt4', поставляемый с cx_freeze, некорректно работает на Mac. Кто-нибудь может «собрать» и запустить этот пример на Mac?! Я не мог найти никакой информации по этой, казалось бы, простой проблеме на форумах.

Действительно, сначала построим:

~$ cd cx_Freeze-4.3.3/cx_Freeze/samples/PyQt4/
PyQt4$ ls
    PyQt4app.py setup.py
PyQt4$ python setup.py build
    running build
    running build_exe
    creating directory build/exe.macosx-10.5-x86_64-2.7
    copying //anaconda/lib/python2.7/site-packages/cx_Freeze-4.3.3-py2.7-
    macosx-10.5-x86_64.egg/cx_Freeze/bases/Console -> build/exe.macosx-10.5-x86_64-2.7/PyQt4app
    TD bug fix: adding //anaconda/lib to relative path libpython2.7.dylib!
    copying //anaconda/lib/libpython2.7.dylib -> build/exe.macosx-10.5-x86_64-2.7/libpython2.7.dylib
    TD bug fix: adding //anaconda/lib to relative path libpython2.7.dylib!
    writing zip file build/exe.macosx-10.5-x86_64-2.7/library.zip
    …
    copying //anaconda/lib/python2.7/lib-dynload/zlib.so -> build/exe.macosx-10.5-x86_64-2.7/zlib.so
PyQt4$

обратите внимание на строки «TD bug fix…»: для того, чтобы описанное выше работало без ошибки «файл не найден», мне пришлось добавить исправление к функции _GetDependentFiles в файле cx_freeze freezer.py:

for i in range(len(dependentFiles)):
    filei = dependentFiles[i]
    if not os.path.isabs(filei):
        print 'TD bug fix: adding ' + sys.prefix + '/lib to relative path ' + filei + '!'
        dependentFiles[i] = os.path.join(sys.prefix,'lib',filei)

Теперь при попытке запустить созданную автономную программу получаю:

PyQt4$ ls
    PyQt4app.py  build  setup.py
PyQt4$ cd build/exe.macosx-10.5-x86_64-2.7/
exe.macosx-10.5-x86_64-2.7$ ls
    PyQt4.QtCore.so _codecs_iso2022.so _struct.so   libQtCore.dylib    libz.1.dylib
    PyQt4.QtGui.so  _codecs_jp.so      binascii.so  libQtGui.4.dylib   sip.so
    PyQt4app        _codecs_kr.so      bz2.so       libQtGui.dylib     unicodedata.so
    _codecs_cn.so   _codecs_tw.so      itertools.so libpython2.7.dylib zlib.so
    _codecs_hk.so   _multibytecodec.so libQtCore.4.dylib library.zip
exe.macosx-10.5-x86_64-2.7$ ./PyQt4app
    Traceback (most recent call last):
      File "//anaconda/lib/python2.7/site-packages/cx_Freeze-4.3.3-py2.7-macosx-10.5-x86_64.egg/cx_Freeze/initscripts/Console.py", line 27, in <module>
        exec(code, m.__dict__)
      File "PyQt4app.py", line 5, in <module>
      File "ExtensionLoader_PyQt4_QtGui.py", line 22, in <module>
      File "ExtensionLoader_PyQt4_QtGui.py", line 14, in __bootstrap__
    ImportError: dlopen(/Users/thomasdeneux/cx_Freeze-4.3.3/cx_Freeze/samples/PyQt4/build/exe.macosx-10.5-x86_64-2.7/PyQt4.QtGui.so, 2): Library not loaded: @loader_path/../../../libQtGui.4.dylib
      Referenced from: /Users/thomasdeneux/cx_Freeze-4.3.3/cx_Freeze/samples/PyQt4/build/exe.macosx-10.5-x86_64-2.7/PyQt4.QtGui.so
      Reason: image not found
exe.macosx-10.5-x86_64-2.7$

Бывает, что некоторые библиотеки Qt не найдены из-за того, что на них указан полный относительный путь, а в раздаче все библиотеки были скопированы внутри одной папки.

Затем я перешел на Py2App, надеясь, что другой пакет не столкнется с такой проблемой. Я не показываю сейчас все детали, только самые важные строки при попытке сборки (на этот раз мне не нужно было изменять код, чтобы запустить сборку) и запустить еще одну простую программу helloworld на основе Qt:

test$ py2applet --make-setup helloworld.py
    Wrote setup.py
test$ python setup.py py2app
    running py2app
    creating /Users/thomasdeneux/Documents/spyderworkspace/securebox/python/build/bdist.macosx-10.5-x86_64
    ...
    Done!
test$ ./dist/helloworld.app/Contents/MacOS/helloworld 
    Traceback (most recent call last):
      File "/Users/thomasdeneux/Documents/spyderworkspace/securebox/python/dist/helloworld        .app/Contents/Resources/__boot__.py", line 351, in <module>
        _run()
      File "/Users/thomasdeneux/Documents/spyderworkspace/securebox/python/dist/helloworld        .app/Contents/Resources/__boot__.py", line 336, in _run
        exec(compile(source, path, 'exec'), globals(), globals())
      File "/Users/thomasdeneux/Documents/spyderworkspace/securebox/python/dist/helloworld        .app/Contents/Resources/helloworld.py", line 4, in <module>
        from PyQt4.QtGui import *
      File "PyQt4/QtGui.pyc", line 14, in <module>
      File "PyQt4/QtGui.pyc", line 10, in __load
    ImportError: dlopen(/Users/thomasdeneux/Documents/spyderworkspace/securebox/python/dist/helloworld.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtGui.so, 2): Library not loaded: @loader_path/../../../libQtGui.4.dylib
      Referenced from: /Users/thomasdeneux/Documents/spyderworkspace/securebox/python/dist/helloworld.app/Contents/Resources/lib/python2.7/lib-dynload/PyQt4/QtGui.so
      Reason: image not found
    2015-05-16 20:40:41.546 helloworld[983:707] helloworld Error
test$ 

Возникает точно такая же проблема!

Спасибо всем, кто может помочь, будь то непосредственное решение проблемы или совет по другой стратегии создания автономных программ для Mac из проектов python/Qt.


person Thomas    schedule 13.07.2015    source источник
comment
Я переключился на py2app и установку python с помощью homebrew. Это работает для меня.   -  person mr_js    schedule 19.07.2015
comment
(попробую и отпишусь о результате)   -  person Thomas    schedule 21.07.2015