Не удалось создать автономное приложение 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…": чтобы запустить вышеописанный файл без ошибки "файл не найден", мне пришлось добавить исправление в функцию _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.