Распространяем python-приложения на Windows (и разбираемся с проблемами)

Хотя я предпочитаю linux, как свою основную операционную систему, где мне наиболее комфортно работать, частенько приходится загружаться и в Windows (а, еще, чем черт не шутит, и в мак). И (к сожалению) не только чтобы запустить steam, пристрелить пару гоблинов или побротить по VR мирам.

Недавно надо было отгрузить питоновское приложение для пользователей windows. А на windows, как водится, без проблем ничего не обходится. И в тот момент закономерный вопрос — почему просто не через pip? А вот уже пошли дьявольские подробности, которые я описал у себя в бложике.

Потому что какую-то картинку воткнуть надо было…

Почему не pip? (Придется качать. И качать много!)

Приложение у меня вообще опенсурсное, проблем с ним особенных нет. И в pip я закинул релиз очень давно, так что все нормальные люди (у кого linux) просто набирают ‘pip install rumboot-tools’ и все «просто работает» ™ Почему же это не прокатывает в Windows?

Как оказалось, есть несколько зависимостей (Например, netifaces) которые pip при установке на windows будет собирать из исходников. А для этого потребуется Visual Studio Build Tools. А это 6+GB для выкачки из интернета. А так как некоторые потребители сидят за прокси ограничивающим скорость (чтобы не было соблазна смотреть порнуху в офисе!) то и выкачать столько является проблемой. До кучи эффективные менеджеры из MS с гоблинским чувством прекрасного, тягой к садомазохизму и отсутствием QA, запихнули ссылку на скачку в самую задницу страницы, а предлагают скачать не дистрибутив, а установщик, который сам тянет файлы из интернета и не всегда подхватывает настройки прокси. В общем, из нескольких человек «простых пользователей», ставших подопытными кроликами, меньше половины даже просто нашли ссылку на скачку, а самые упорные застряли на настройке прокси. И после этого M$ утверждает в рекламе, что Linux — не дружественная пользователю система.

Пробуем venv (Не прокатило)

А что если сделать venv, заархивировать и отгрузить? Не сработало. Venv прописывает абсолютные пути к установленному питону, и выходит чехарда с версиями и путями установки. Получившаяся система будет хрупкой и требовать строго определенной версии питона в системе по строго определенному пути. А если вспомнить, что виндузятники до сих пор страдают от необходимости различать 32 и 64 бит программы… А так как сама программа, это просто набор инструментов для работы из командной строки, то пользователю еще надо будет прописать и PATH!

PyInstaller (Точно не то решение, которое мы ищем)

С ним я мучался долго и не все документировал. Потому скажу просто — не заработало. Опять, как и в случае с venv нужна строго определенная версия питона, питон он с собой не пакет. К сожалению, питон оно с собой не заворачивает. К тому же потребуется писать, поддерживать и тестировать manifest для pyinstaller’а.

Стэндэлон сборка питона (Почему бы и нет?)

Идея красивая. Взять собранный питон, без всяких установщиков. Вкорячить ему нужные пакеты и запаковать для пользователей. Но не все так просто. У такого питона нет pip’а из коробки (Можно добавить, но официально не поддерживается). Самое дуракоскойкое(tm) решение, так как мы все отгружаем в одном архиве. Но собрать такой пакет непросто. Даже после установки pip’а в таком вот питоне нет хэдеров и собрать нативные расширения не получится. И потом все равно придется делать свой установщик.

WheelHouse (Серебряная пуля!)

После изрядного количества времени убитого в весьма некомфортной для работы среде и убогой командной строке cmd, я нашел, что в питоне оказывается есть простое и красивое решение проблемы. Может быть настолько очевидное, что его даже не обсуждали на стэковерфлоу и других технокурилках. pip может собрать так называемые ‘wheels’ (колеса? Скорее всего имелить в виду «кольца», в которые укладывается змея). Это бинарные пакеты! И часть того, что прилетает из pip уже является собранными wheels’ами, но у части моих зависимостей собранной под винду версии не было, отсюда и проблемы.

Еще лучше — pip может по щелчку пальцев собрать wheel’ы для твоего пакета и всех зависимостей! Просто набираем в директории проекта и «откидываемся на спинку табуретки», как во время установки Windows 98 в детстве.

pip wheel .

Результат жизнедеятельности — пачка wheel’ов ! Теперь надо это проделать для разных версий питона, которые поддерживает приложение (у меня это 3.7, 3.8, 3.9) и для 32 и 64 bit версий. И сгенерить орочий install.cmd который «накатит все эти колеса в систему». Дальше в архив и отгружаем. Звучит как задача для CI.

Такой набор файлов называется ‘wheelhouse’ у матерых питонистов. И еще есть нюанс при их установке. Так как зависимости мы все обработали, когда генерировали это все хозяйство, то надо сказать pip’у чтобы он не пытался что-то скачивать из интернета (—no-index) и не пытался разрешить зависимости (—no-deps) (Иначе придется генерировать список для установке в порядке зависимостей).

В итоге install.cmd скрипт будет выглядеть примерно так:

pip install --no-index --no-deps pkg1.wheel
pip install --no-index --no-deps pkg2.wheel
pip install --no-index --no-deps pkg3.wheel
pip install --no-index --no-deps pkg4.wheel
...

Ставить можно как глобально (в PATH ничего не надо добавлять, оно и так туда попадет) или в venv (в PATH добавит пользователь). И VS Build Tools больше не нужны. Осталось только настроить CI.

Для винды я выбрал appveyor. Он все чаще встречается для windows-проектов. «Visual Studio 2019» образ уже содержал все нужные версии питона под 32 и 64 бита. Немного магии с деплойментом и на каждый тег собираются zip’ы под все версии питона и прикрепляются к странице релизов на github. PROFIT!

Испытания на добровольцах такой способ прошел без проблем.

Пример

Кому интересно, проект можно посмотреть тут rumboot-tools.

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

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.