Пользователь
0,0
рейтинг
19 января 2015 в 12:45

Разработка → Создаём окружение для PyQt5 в Linux MInt (Ubuntu) tutorial

Qt*, Python*
image image image
Давно уже до пятой версии обновился Qt и вместе с ним PyQt, но найти информацию по ним в русскоязычном сегменте — задача не из простых. Под катом подробный туториал для тех, кто только начинает знакомиться со связкой Qt + python3.

Цель: собрать и настроить окружение, пройти путь от установки PyQt5 и создания формы в Qt Designer до запуска переносимого бинарника под Windows (да, всё верно, разрабатываем под Mint, собираем для linux и windows).



Пути установки


Исходя из того, что мы — совсем новички, я постараюсь использовать пути в системе, которые используются по-умолчанию, или которые мы создадим исходя из следующей логики размещения:
  • Все необходимые файлы и папки хранятся в директории dev в домашней директории пользователя, т.е. ~/dev/
  • Мы будем использовать виртуальные окружения для питона, и хранить их будем в директории envs, т.е. ~/dev/envs/
  • Наши проекты будут храниться в директории src, т.е. ~/dev/src/

Если у вас уже сложилась собственная иерархия размещения файлов, то придётся скорректировать пути в командах, приведённых ниже.

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


Создаём структуру директорий. Откройте консоль и выполните:
cd ~
mkdir -p dev/envs dev/src
cd dev/envs

Ставим пакет, который потребуется нам для сборки в будущем:
sudo apt-get install python3-dev

Ставим pip и virtualenv:
wget https://bootstrap.pypa.io/get-pip.py
sudo python3 get-pip.py
rm get-pip.py
sudo pip install virtualenv

Создаём виртуальное окружение, активируем его и обновляем пакеты:
virtualenv --prompt="[pyqt5] " pyqt5
source pyqt5/bin/activate
pip install -U pip setuptools

Ставим Qt5. При выборе пути установки я оставил «по-умолчанию» ~/Qt. Если Вы выберите другой, то необходимо менять пути в командах ниже:
# Для x64-архитектуры
# http://www.qt.io/download-open-source/#section-2
wget http://download.qt-project.org/official_releases/online_installers/qt-opensource-linux-x64-online.run
chmod u+x qt-opensource-linux-x64-online.run
./qt-opensource-linux-x64-online.run
rm qt-opensource-linux-x64-online.run

# Для x86-архитектуры
# http://www.qt.io/download-open-source/#section-2
# wget http://download.qt-project.org/official_releases/online_installers/qt-opensource-linux-x86-online.run
# chmod u+x qt-opensource-linux-x86-online.run
# ./qt-opensource-linux-x86-online.run
# rm qt-opensource-linux-x86-online.run

Ставим SIP — модуль, необходимый для работы PyQt:
# http://www.riverbankcomputing.com/software/sip/download
wget http://sourceforge.net/projects/pyqt/files/sip/sip-4.16.5/sip-4.16.5.tar.gz
tar xvzf sip-4.16.5.tar.gz
cd sip-4.16.5/
python configure.py -d ~/dev/envs/pyqt5/lib/python3.4/site-packages/
make
sudo make install
sudo make clean
cd ..
rm -rf sip*

Ставим PyQt:
wget http://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.4/PyQt-gpl-5.4.tar.gz
tar xvzf PyQt-gpl-5.4.tar.gz
cd PyQt-gpl-5.4/
# У меня под рукой только x64-архитектура, поэтому моя команда выглядит именно так.
# Если же у вас x86, то путь ~/Qt/5.4/gcc_64/bin/qmake будет выглядеть иначе.
# Буду признателен, если в комментариях подскажут, как именно
python configure.py --destdir ~/dev/envs/pyqt5/lib/python3.4/site-packages/ --qmake ~/Qt/5.4/gcc_64/bin/qmake
make
sudo make install
sudo make clean
cd ..
rm -rf PyQt*

На этом всё. Окружение установлено и готово к работе. Для проверки выполните команду:
python -c "from PyQt5.QtCore import QT_VERSION_STR;from PyQt5.Qt import PYQT_VERSION_STR;from sip import SIP_VERSION_STR;print('Qt version: ',QT_VERSION_STR);print('SIP version: ',SIP_VERSION_STR);print('PyQt version: ',PYQT_VERSION_STR)"

Ответ должен выглядеть следующим образом:
Qt version:  5.4.0
SIP version:  4.16.5
PyQt version:  5.4

Для проверки, что всё действительно установилось в виртуальное окружение, откройте новое окно терминала и повторите команду проверки:

В ответ должна появиться ошибка ImportError. Новое окно терминала после этого можно закрыть.

Создание приложения


Перейдём в директорию с нашими исходниками и создадим директорию проекта:
cd ../src/
mkdir pyqt_test
cd pyqt_test/

Далее нам потребуется Qt Designer. Если Вы не меняли пусть установки Qt, то запустить его можно командой:
# И вновь эта команда будет работать только для x64-архитектуры.
# Для x86 вместо gcc_64 вероятнее всего будет иная директория.
~/Qt/5.4/gcc_64/bin/designer

Вот так выглядит запущенный Qt Designer на моей системе:

В данном руководстве я не буду подробно останавливаться на описании интерфейса дизайнера, мы пройдём простейший путь до минимальной готовой формы. Если Вам необходима более подробная информация — Google It!

В диалоговом окне выбираем «Widget» (последний пункт в списке «templates/forms») и нажимаем кнопку «Создать». Откроется форма редактирования виджета:


Перетащите на форму кнопку из меню слева и сохраните полученную форму с именем test.ui в директорию ~/dev/src/pyqt_test/:

Tips&Tricks: Нажав [Crtl + R] Вы можете запустить свою форму и «потрогать» её в режиме реального времени.

Конвертируем файл интерфейса из XML формы в понятную python форму:
pyuic5 test.ui > test_ui.py

Я не хочу редактировать что-либо в файле, созданном конвертером PyQt, поэтому наши слоты мы опишем в отдельном файле. Создайте файл test_slots.py и откройте его в любимом Вами редакторе. Наполнение файла должно выглядеть примерно так:
"""
Пользовательские слоты для виджетов.
"""
# Импортируем модуль времени
from datetime import datetime
# Импортируем класс интерфейса из созданного конвертером модуля 
from test_ui import Ui_Form


# Создаём собственный класс, наследуясь от автоматически сгенерированного
class MainWindowSlots(Ui_Form):
    
    # Определяем пользовательский слот
    def set_time(self):
        # Получаем текущую метку времени в формате 'Ч:М:С'
        str_time = datetime.now().strftime('%H:%M:%S')
        # Присваиваем надписи на кнопке метку времени
        self.pushButton.setText(str_time)
        return None


Затем, создайте ещё один файл с именем main.py, в котором мы опишем основную логику:
"""
Основной скрипт программы.
Запускает конфигуратор окна, подключает слоты и отображает окно.
"""
# Импортируем системый модуль для корректного закрытия программы
import sys
# Импортируем минимальный набор виджетов
from PyQt5.QtWidgets import QApplication, QWidget
# Импортируем созданный нами класс со слотами
from test_slots import MainWindowSlots


# Создаём ещё один класс, наследуясь от класса со слотами
class MainWindow(MainWindowSlots):

    # При инициализации класса нам необходимо выпонить некоторые операции
    def __init__(self, form):
        # Сконфигурировать интерфейс методом из базового класса Ui_Form
        self.setupUi(form)
        # Подключить созданные нами слоты к виджетам
        self.connect_slots()

    # Подключаем слоты к виджетам
    def connect_slots(self):
        self.pushButton.clicked.connect(self.set_time)
        return None

if __name__ == '__main__':
    # Создаём экземпляр приложения
    app = QApplication(sys.argv)
    # Создаём базовое окно, в котором будет отображаться наш UI
    window = QWidget()
    # Создаём экземпляр нашего UI
    ui = MainWindow(window)
    # Отображаем окно
    window.show()
    # Обрабатываем нажатие на кнопку окна "Закрыть"
    sys.exit(app.exec_())

На этом наше приложение завершено. Выполнив из консоли
python main.py

мы должны увидеть форму с кнопкой посередине, нажатие на которую меняет название кнопки на системную дату.


Упаковка в исполняемый файл для Linux


Упаковщик потребует некоторой магии при установке.
Скачиваем пакет, не устанавливая его и распаковываем:
cd ../../envs/pyqt/
pip install -d . cx_freeze
tar xvfz cx_Freeze-4.3.4.tar.gz

Открываем любимым редактором файл cx_Freeze-4.3.4/setup.py. Я использую SublimeText:
subl cx_Freeze-4.3.4/setup.py

Правим строку №84, чтобы она выглядела, как на картинке:

Tips&Tricks: А вы знали, что если запустить SublimeText из виртуального окружения, то интерпретатором по-умолчанию будет из виртуального окружения?

Сохраняем изменения, закрываем редактор, устанавливаем пакет, возвращаемся в папку с исходниками, запускаем упаковку:
cd cx_Freeze-4.3.4
python setup.py install
rm ../cx_Freeze-4.3.4.tar.gz
cd ../../../src/pyqt_test
cxfreeze main.py --target-dir=nix_build

После этого в директории с исходниками появится директория dist, в которой среди множества файлов можно заметить файл без расширения main — это и есть наш бинарник, готовый для запуска и переноски. Откровенно говоря, немного расстраивает размер дистрибьютива: на моей машине это — 70,1 Мб, но не стоит забывать, что туда упакованы: python, PyQt, Qt и некоторые общесистемные библиотеки. Сборочный скрипт cxfreeze достаточно гибко конфигурируется, но подбор оптимальных параметров я оставлю на совести читателя. Скажу только, что счастье кроется в сжатии, оптимизации и ручном ограничении зависимостей.

Упаковка в исполняемый файл для Windows


К сожалению, чуда не будет. Мне не известен способ собрать exe напрямую из-под Linux-системы. Поэтому, придётся потанцевать с wine.
Закрываем открытый в самом начале терминал:
deactivate
exit

Открываем новый, ставим последнюю версию wine:
cd dev
sudo add-apt-repository ppa:ubuntu-wine/ppa
sudo apt-get update
sudo apt-get install wine1.7

После этого скачиваем windows-версии уже знакомых нам пакетов и запускаем установку из-под wine:
# https://www.python.org/downloads/windows/
wget https://www.python.org/ftp/python/3.4.2/python-3.4.2.msi
wine msiexec /i python-3.4.2.msi
rm python-3.4.2.msi
# http://www.riverbankcomputing.com/software/pyqt/download5
wget http://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.4/PyQt5-5.4-gpl-Py3.4-Qt5.4.0-x32.exe
wine PyQt5-5.4-gpl-Py3.4-Qt5.4.0-x32.exe
rm PyQt5-5.4-gpl-Py3.4-Qt5.4.0-x32.exe
# http://sourceforge.net/projects/cx-freeze/files/
wget http://downloads.sourceforge.net/project/cx-freeze/4.3.3/cx_Freeze-4.3.3.win32-py3.4.msi
wine msiexec /i cx_Freeze-4.3.3.win32-py3.4.msi
rm cx_Freeze-4.3.3.win32-py3.4.msi

А дальше немного магии. Идём по ссылке:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#cx_freeze

Качаем актуальную версию cx_Freeze для нашего интерпретатора и ставим поверх официальной:
wine cx_Freeze-4.3.4.win32-py3.4.exe
rm cx_Freeze-4.3.4.win32-py3.4.exe

После этого остаётся проверить работоспособность. Переходим в каталог с исходником, открываем терминал wine, выполняем уже знакомую команду сборки:
cd src/pyqt_test
wine cmd
cxfreeze main.py --target-dir=win_build

Оказалось, что у меня в распоряжении нет windows-машины, поэтому смог протестировать результат только под wine. Выходим из терминала wine (команда exit), закрываем терминал. Идём раздавать нашу программу всем желающим.

P.S.: Все исходники на GitHub`е
Захар Скороходов @ZAhmed
карма
12,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (7)

  • 0
    К слову говоря, в Ubuntu магия с установщиком cxFreeze не нужна

    python -c "import distutils.sysconfig; print(distutils.sysconfig.get_config_var('Py_ENABLE_SHARED'))"
    возвращает 1

    Почему на Mint это не так? Или это локальные проблемы?
    • 0
      Откровенно говоря, я предметно не разбирался в сути бага, но насколько я понял из поверхностного изучения, по-умолчанию python3 собирается без флага --enable-shared. Я был абсолютно удовлетворён этой версией, пока не выполнил Ваше тест в своём virtualenv. У меня тоже вернуло 1. О.о
  • +2
    Почему бы просто не поставить pyqt5 из репозитория?

    # apt-get install python3-pyqt5 pyqt5-dev-tools
    
    • –2
      Я не сторонник сваливания в кучу. В virtualenv всё аккуратно и по полочкам, а также можно спокойно поставить PYQt4, PyQt5, 6 и т.д. И не бояться, что они будут друг с другом воевать за место под солнцем.
      • +4
        Просто как мэйнтейнер Qt/PyQt в Ubuntu, я знаю, как много времени занимает компиляция (особенно, если хочется WebKit). Именно поэтому в Ubuntu уже есть готовые пакеты для всех версий Python для тех, кому они нужны. И собраны с поддержкой WebKit, WebSockets и прочих модных технологий.

        А ещё PyQt4 и PyQt5 прекрасно встают друг рядом с другом (про PyQt6 такого сказать не могу, так как его ещё даже в планах нет).
        • –1
          Откровенно говоря, я не знаю, что Вам ответить. :) Во-первых, извините, что не заключил слова про PyQt6 в тег >sarcasm<, думал будет очевидно. Во-вторых, с удовольствием прочитаю ваш пост на темы «Почему PyQt надо ставить из репозиториев», «За что я ненавижу virtualenv», «Как меня достали юзеры, которые не пользуются тем, что о них заботятся» или около того.
          А если серьёзно, спасибо за отличный инструмент, в разработке которого Вы принимаете участие. Ещё бы из pip он ставился — была бы вообще просто сказка и конец tkinter.
          • +3
            Я просто оставлю это здесь.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.