Pull to refresh

Настраиваем окружение на Mac OS и собираем автономное приложение с PySide/PyQt

Reading time5 min
Views27K
image
Сейчас все удобнее становится использовать HTML и JavaScript в интерфейсах приложений. И именно такая задача недавно появилась передо мной, с одним важным условием — на выходе должно быть полностью standalone приложение, не требующее установки дополнительных библиотек и способное запуститься в обычном пользовательском окружения.

В силу своего природного обаяния в качестве основного языка был выбран Python + PySide c WebKit на борту, для сборки app-бандла использовался py2app.

Проблемы появились, при первой же попытке запустить приложение на чистой системе — обнаружилось большое количество внешних зависимостей, которые py2app не смог самостоятельно разрешить. Под катом пошаговая инструкция как эта проблема была решена.

В попытках понять почему py2app не включает в бандл все необходимые библиотеки, в одной статье была найдена мысль, что создание полностью автономного приложения с встроенным в Mac OS интерпретатором невозможно и нужно пользовать MacPort. Так и поступим.

Подготовка


Итак, нам потребуется:
  1. XCode
  2. MacPorts
  3. Python
  4. virtualenv
  5. Qt4
  6. PySide
  7. py2app

XCode


Несет в себе как средства разработки под Mac OS, так и нужный нам gcc.
Я использовал последнюю версию — 4.2, но и с более ранними (3.Х) проблем быть не должно.
Если еще нет, то брать с установочных дисков Mac OS или с сайта Apple (потребуется бесплатная регистрация)

MacPorts


Менеджер пакетов, который позволяет ставить на мак много полезных тулов и библиотек.
Устанавливается стандартным способом (pkg). Брать с MacPorts.org.
После установки можно на всякий случай обновить:
$ sudo port selfupdate

Python


Ставим из MacPorts:
$ sudo port install python27
Если используете другую версию питона, просто замените здесь и далее.

virtualenv


Тул, позволяющий создавать изолированные окружения для питона. Очень удобно, когда нужно иметь несколько версий питона или разные проекты требуют различных библиотек, упрощает дальнейший деплоймент. В нашем случае мы с помощью virtualenv создадим «автономную песочницу» из которой и появится standalone приложение.
$ sudo easy_install virtualenv

В нагрузку ставим virtualenvwrapper, который упрощает работу с окружением:
$ sudo easy_install virtualenvwrapper

Qt4


Ставим с оф. сайта, я использовал Cocoa: Mac binary package for Mac OS X 10.5 — 10.6

PySide


Библиотека для Python, позволяющая использовать всю мощь и силу Qt из привычного языка программирования.
Пытался установить PySide сразу в виртуальное окружение через pip или easy_install (что было бы логичнее), но выяснилось, что PySide не поставляется в необходимом для этих менеджеров пакетов виде, в результате чего куча времени была убита на попытки скомпилировать библиотеку… остановился через пару дней, когда поймал себя за тем, что сидел и правил исходники какой-то сторонней либы =)
В результате идем путем установки предоставляемого разработчиками пекеджа.

Настройка окружения


Подготовительная часть на этом закончена, переходим непосредственно к созданию виртуального окружения и его наполнению.

Создаем виртуальное окружение


Выбираем место где будет жить окружение, для этого в ~/.bash_profile добавляем
export WORKON_HOME=~/Envs
source /usr/local/bin/virtualenvwrapper.sh


Создаем окружение
$ . ~/.bash_profile
$ mkdir -p $WORKON_HOME
$ mkvirtualenv --no-site-packages --python=/opt/local/bin/python2.7 py27
# --no-site-packages - говорит, что виртуальное окружение не будет использовать системные пекеджи
# --python=/opt/local/bin/python2.7 - какой интерпретор будет использоваться
# py27 - название окружения


После этого в $WORKON_HOME/py27 будет создана базовая структура каталогов и необходимые файлы. Кроме того окружение станет активным, в начале командной строки появится (py27). В дальнейшем, для активации нужно будет выполнить
$ workon py27

Можно вызвать питон, убедиться, что запустилась правильная версия.
(py27) $ python
Python 2.7.2 (default, Jul 21 2011, 01:27:20)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>


Теперь нужно перенести в новое окружение все библиотеки и модули:
# PySide packages
$ cd /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages
$ mv PySide/ ~/Envs/py27/lib/python2.7/site-packages/
$ mv pysideuic/ ~/Envs/py27/lib/python2.7/site-packages/

# PySide libs
$ cd /usr/lib/
$ sudo mv libpyside-python2.7.* ~/Envs/py27/lib/

# Необходимая для PySide библиотека
$ sudo mv libshiboken-python2.7.* ~/Envs/py27/lib/

# Qt4 libs
$ cd /Library/Frameworks/
$ cp -pR Qt* ~/Envs/py27/lib/
$ cp -pR phonon.framework ~/Envs/py27/lib/ #Обратите внимание на отсутствие слеша после framework!

# Остатки Qt нам не нужны, удаляем
$ sudo /Developer/Tools/uninstall-qt.py


Так, почти все готово, осталась финальная полировка и проверка.

virtualenvwrapper кроме удобного способа создания и активации окружений предоставляет хуки на различные события — preactivate, postactivate, predeactivate, postdeactivate и прочие (полный список). Нас сейчас интересует postactivate, в который мы добавим переменные, которые будут говорить где искать в нашем окружении библиотеки и разные модули.
$ vi ~/Envs/py27/bin/postactivate
# Добавляем туда
export DYLD_FRAMEWORK_PATH=~/Envs/py27/lib/
export DYLD_LIBRARY_PATH=~/Envs/py27/lib/


Быстрая проверка:
$ workon py27
(py27) $ python
Python 2.7.2 (default, Jul 21 2011, 01:27:20)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import PySide
>>> PySide
<module 'PySide' from '/Users/smaant/Envs/py27/lib/python2.7/site-packages/PySide/__init__.pyc'>
>>>


Если вы все сделали правильно — то результат должен быть примерно таким. Если словили кучу ошибок, то… возможны варианты :)

py2app и проверка боем


Теперь все готово к написанию тестового приложения — qt_test.py:
#!/usr/bin/env python

import sys
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtWebKit import *

app = QApplication(sys.argv)

web = QWebView()
web.load(QUrl("http://www.pyside.org/"))
web.show()

sys.exit(app.exec_())


Проверяем
$ workon py27
(py27) $ python qt_test.py

image

py2app


Пришла очередь py2app, который поможет собрать наше приложение в полноценный бандл. Кроме прочего разработчики virtualenv заботливо положили в наше виртуальное окружение еще один менеджер пакетов pip, с помощью которого мы и поставим py2app:
$ workon py27
(py27) $ pip install py2app


Для генерации бандла py2app использует специальный файл — setup.py. Как его создать с нуля хорошо рассказано в доке, а мы воспользуемся уже готовым:
from setuptools import setup

APP = ['qt_test.py']
OPTIONS = {'argv_emulation': False,
           'includes' : ('PySide.QtNetwork', ),
           'semi_standalone': 'False',
           'compressed' : 'True',
           'frameworks' : ('libpyside-python2.7.1.0.dylib', 'libshiboken-python2.7.1.0.dylib'),
          }

setup(
    app=APP,
    options={'py2app': OPTIONS},
    setup_requires=['py2app'],
)


В папочке dist появится app-бандл, который вы непременно можете запустить! )
Весь алгоритм проверялся на Mac OS X 10.6.8, а получившийся бандл тестировался на такой же, но чистой системе.

Если вы хотите использовать PyQt, то последовательность действий будет точно такой же, только ставится pyqt и в исходных файла все PySide заменяются на PyQt. Так же, возможно, потребуется установить SIP, аналогичным образом перенести его в виртуальное окружение и добавить в includes в setup.py.

Ссылки


Ниже полный список тулов и библиотек, которые я использовал, с их версиями:

Две статьи, которые мне сильно помогли:
How to make standalone OS X application bundles from PyQt apps using py2app
Multiple Python Versions on OSX with Virtualenv and Macports
Tags:
Hubs:
Total votes 42: ↑40 and ↓2+38
Comments18

Articles