Персональный сайт Александра Литовченко

номер32
Поиграть в преферанс в онлайне
2 июля 2008 16:33

Py2Exe: Разворачиваем Python-приложения на Windows платформе

При разработке подавляющего большинства python-приложений рано или поздно встает вопрос о разворачивании приложений на конечной машине пользователя под управлением windows. Требовать от пользователя установленного python с нужными библиотеками негуманно, и тут на помощь приходит Py2Exe (или аналоги).

Прежде всего нужно понимать, что никакого полноценного exe из python-приложения получить невозможно в принципе в силу динамичности языка. Все на что способны подобные «компиляторы», это запаковать python-интерпретатор и все используемые библиотеки в виде pyd и pyc файлов в zip архив и сгенерировать простой stub в виде exe файла который умеет вызвать из архива интерпретатор python и передать ему управление (привет начало 90-х, здравствуй Clipper).

Несмотря на все ограничения и недостатки, этот способ основную задачу «пользователь скачал exe и запустил ничего дополнительно не устанавливая« вполне себе решает.

К сожалению чудес не бывает, и разработчики сталкиваются с массой проблем при подготовке дистрибутивов таким образом. Любая более-менее нетривиальная python-программа разработанная без учета последующего использования Py2Exe скорей всего не заработает. Рассмотрим очевидные (и не очень ньюансы).

Где я нахожусь

Любителей определять каталог запуска приложения по os.path.dirname(__file__) ждет неприятный сюрприз. __file__ будет указывать внутрь zip архива а не в каталог нахождения exe файла.

import os, sys

def module_path():
    if hasattr(sys, "frozen"):
        return os.path.dirname(
            unicode(sys.executable, sys.getfilesystemencoding( ))
        )
    return os.path.dirname(unicode(__file__, sys.getfilesystemencoding( )))

Вместо этого следует использовать функцию module_path

Динамический импорт

Это самая распространенная проблема. Про динамический импорт придется забыть. Точнее все модули которые могут быть динамически импортированы в приложении должны быть импортированы явно в главном модуле. Включая те, которые могут быть импортированы из системных библиотек. Используете PIL? Будьте добры явно импортировать

import JpegImagePlugin
import TgaImagePlugin
import PngImagePlugin
import GifImagePlugin
....

И все плагины форматов которые могут понадобиться для работы приложения.

Где мои файлы данных

Все файлы с данными должны быть перечислены в конфигурации для py2exe после чего будут скопированы в дистрибутив при билде проекта автоматически. Этот процесс хорошо описан в документации, и на нем останавливаться смысла особого нет. А вот все открытия файлов данных должны производиться по абсолютным путям. Правило «абсолютных путей» при работе с Py2Exe должно использоваться повсеместно. Используете gettext? Укажите абсолютный путь по которому лежат ваши .mo файлы в gettext.translation. Читаете конфиг? Откройте его абсолютному пути. Пишете в лог? Создайте его по абсолютному пути.

Что делать если заранее не знаете абсолютного пути? Возьмите из конфиг файла. По какому пути искать свой конфиг файл? Спросите у выше описанной функции module_path, в реестре, у пользователя, где угодно, но никогда не используйте относительных путей.

Windows Services + Twisted

При этой связке была обнаружена одна неприятная особенность. Если в SvcDoRun просто запустить reactor.run() то служба стартует, но тут же останавливается с жалобой, мол, «мне нечего делать» Исправить ситуацию можно при помощи reactor.run(installSignalHandlers=0).

PyQt4 + Py2Exe

Минимальный скрипт установщика

from distutils.core import setup
import py2exe

setup(
    windows=[{"script":"vhrvoice.pyw"}], 
    options={"py2exe": {"includes":["sip"]}}
)

Не забудьте добавить sip в проект. Иначе ваше PyQT4 приложение не соберется.

Комментарии

1 22 апреля 2010 21:26, Александр

Хорошо, весело, остроумно - особо понравилось про милый сердцу добрый Clipper от Nantucket. Жаль только, что ничего не понятно про то, как в этом троглодите из ру сделать ехе.

Добавить комментарий

только текст. HTML теги вырезаются:

Пожалуйста будьте вежливы при общении