python wheel что это
Tech blog by @dizballanze
Python wheels для быстрой установки зависимостей
Часто все зависимые python пакеты устанавливаются при помощи pip из PyPI и/или VCS. Такой подход имеет ряд недостатков:
Для решения этой проблемы предлагается использование заранее подготовленных пакетов wheel для всех зависимостей и хранение их в репозитории системы.
Создаем архив wheel пакетов
Представим типичный Python проект с файлом requirements.txt содержащим зависимости. Пример файла requirements.txt :
Это делается для того, чтобы при установке из архива wheel пакетов не происходили запросы к внешним VCS, а брались локальные wheel, которые мы сейчас будем генерировать.
Cоздаем и активируем venv :
Устанавливаем все пакеты как обычно, но из requirements-remote.txt :
Сгенерируем архив всех пакетов PyPI, всех их зависимостей и всех зависимостей внешних пакетов (VCS). Для этого нам потребуется свежая версия pip и пакет wheel :
После этого получаем архив wheel пакетов для всех зависимостей кроме внешних (VCS). Для внешних пакетов устанавливаемых из исходников необходимо сгенерировать пакеты вручную при помощи setup.py bdist_wheel :
Теперь в директории wheels есть все необходимые пакеты для установки всех зависимостей системы. Процесс уставновки зависимостей из локального архива пакетов выполняется так:
Тестирование скорости установки
Обычная установка со скачиванием пакетов из PyPI и VCS:
Установка из локального архива wheels:
Из результатов можно сделать вывод, что время установки пакетов из локального архива в нашем случае меньше в 4 раза. Что логично, т.к. пакеты заново не скачиваются из интернета и не компилируются.
Бонус
Для удобства написал небольшой скрипт, автоматизирующий сборку пакетов установленных из исходников.
Пример использования скрипта:
Python на колёсах
Инфраструктура системы пакетов для Python долго подвергалась критике как от разработчиков, так и от системных администраторов. Долгое время даже само комьюнити не могло прийти к соглашению, какие именно инструменты использовать в каждом конкретном случае. Уже существуют distutils, setuptools, distribute, distutils2 в качестве базовых механизмов распространения и virtualenv, buildout, easy_install и pip в качестве высокоуровневых инструментов управления всем этим беспорядком.
Несколько лет назад PJE попытался исправить эту проблему, предоставив смесь из setuptools и pkg_resources для улучшения distutils и добавления метаданных в Python-пакеты. В дополнение к этому он написал утилиту easy_install для их установки. По причине отсутствия формата распространения, поддерживающего метаданные, был предоставлен формат ‘яиц’ [egg].
Python eggs – обычные zip-архивы, содержащие python-пакет и необходимые метаданные. Хотя многие люди, вероятно, никогда намеренно не собирали egg’и, их формат метаданных до сих пор жив-здоров. И все разворачивают свои проекты с использованием setuptools.
Потом прошло еще немного времени, и отказ от бинарных пакетов стал доставлять неудобства. Люди всё больше и больше стали деплоить на облачные сервера, а необходимость перекомпиляции C-шных библиотек на каждой машине не слишком радует. Так как ‘яйца’ на тот момент были малопонятны (я так полагаю), их переделали в новых PEP-ах, и назвали ‘колёсами’ [wheels].
В дальнейшем предполагается, что все действия происходят в virtualenv-окружении.
Что за колесо?
Начнём с простого. Что представляют собой ‘колёса’ и чем они отличаются от ‘яиц’? Оба формата являются zip-файлами. Главная разница в том, что egg можно импортировать без распаковки, wheel же придётся распаковать. Хотя нет никаких технических причин, делающих ‘колёса’ неимпортируемыми, поддержка их прямого импорта никогда даже не планировалась.
Другое различие в том, что ‘яйца’ содержат скомпилированные байткод, а ‘колёса’ – нет. Главное преимущество этого в том, что нет необходимости создавать отдельные wheel’ы для каждой версии Python до тех пор, пока не придётся распространять слинкованные через libpython модули. Хотя в новых версиях Python 3 при использовании стабильного ABI даже это уже можно провернуть.
Однако wheel-формат тоже не лишен проблем, некоторые из которых он наследует от ‘яиц’. Например, бинарные дистрибутивы под Linux до сих пор неприемлемы для большинства из-за двух недостатков: Python сам по себе компилируется под Linux в разных формах, и модули линкуются с разными системными библиотеками. Первая проблема вызвана сосуществованием несовместимых версий Python 2: USC2 и USC4. В зависимости от режима компиляции меняется ABI. В настоящее время wheel (насколько я могу судить) не содержит информации о том, с каким режимом Unicode связана библиотека. Отдельная проблема в том, что дистрибутивы Linux меньше совместимы между собой, чем хотелось бы, и обстоятельства могут сложиться так, что сборка, скомпилированная под один дистрибутив, не будет работать на остальных.
Всё это выливается в то, что, вообще говоря, на данный момент бинарные ‘колёса’ нельзя загружать на PyPI как несовместимые с различными системами.
В дополнение ко всему этому wheel сейчас знает только две крайности: бинарные пакеты и пакеты, содержащие чистый python-код. Бинарные пакеты специфичны для Python ветки 2.x. Сейчас это не кажется большой проблемой, потому что цикл 2.x подходит к концу, и пакетов, собранных только для 2.7, хватит надолго. Но если бы вдруг речь пошла про Python 2.8, была бы интересна возможность заявить, что этот пакет не зависит от версии Python, но он содержит бинарники, поэтому он не может не зависеть от архитектуры.
Единственный случай, оправдывающий существование такого пакета – это когда он содержит распределенные библиотеки, загружаемые с ctypes из CFFI. Такие библиотеки не связаны через libpython и не зависимы от реализации языка (их можно использовать даже с pypy).
Но есть и светлая сторона: ничто не запрещает использовать бинарные wheel’ы в своих собственных однородных инфраструктурах.
Сборка колеса
Решение этой проблемы – вручную реализовать Distribution из setuptools, скинув флаг чистоты в false :
Установка колеса
С использованием свежей версии pip ‘колесо’ ставится следующим образом:
Но что с зависимостями? Тут появляются некоторые сложности. Обычно одним из требований к пакету является возможность его установки даже без подключения к интернету. К счастью, pip позволяет отключать загрузку из индекса и устанавливать директорию, содержащую всё необходимое для установки. Если у нас есть wheel’ы для всех зависимостей необходимых версий, можно сделать следующее:
Таким образом будет установлена версия 1.0 пакета package в наше виртуальное окружение.
Колёса для зависимостей
Эта команда выгрузит все пакеты, от которых зависит наш пакет, в указанную папку. Но есть пара проблем.
Первая состоит в том, что в команде в настоящий момент есть баг, который не выгружает зависимости, которые уже являются ‘колёсами’. Так что если зависимость уже доступна на PyPI в wheel-формате, она не будет загружена.
Это временно решается shell-скриптом, который вручную перемещает из кэша скачанные wheel’ы.
Сборка пакетов c использованием DevPI
Такое временное решение проблемы зависимостей вполне применимо в простых ситуациях, но что делать, если есть множество внутренних python-пакетов, зависящих друг от друга? Такая конструкция быстро разваливается.
К счастью, в прошлом году Holker Krekel создал решение этой беды под названием DevPI, который по существу является хаком, эмулирующим работу pip с PyPI. После установки на компьютер DevPI работает как прозрачный прокси перед PyPI и позволяет pip-у устанавливать пакеты из локального репозитория. К тому же все пакеты, скачанные с PyPI, автоматически кэшируются, так что даже если отключить сеть, эти пакеты будут доступны для установки. И, в конце концов, появляется возможность загрузки своих собственных пакетов на локальный сервер, чтобы ссылаться на них так же, как и на хранящиеся в публичном индексе.
После запуска его необходимо единожды проинициализировать:
Так как я использую DevPI ‘для себя’, имена пользователя DevPI и системного пользователя совпадают. На последнем шаге создаётся индекс по имени проекта (при необходимости можно создать несколько).
Для перенаправления pip на локальный репозиторий можно сделать экспорт переменной окружения:
Я размешаю эту команду в скрипт postactivate моего virtualenv для предотвращения случайной загрузки из неверного индекса.
Для размещения собственных wheel’ов в локальном DevPI используется утилита devpi :
Заворачиваем
Теперь всё готово для начала использования внутренних зависимостей и сборки собственных ‘колёс’. Как только они появятся, их можно заархивировать, загрузить на другой сервер и установить в отдельный virtualenv.
Весь процесс станет чуть проще, когда pip wheel перестанет игнорировать существующие wheel-пакеты. А пока приведенный выше shell-скрипт – не худшее решение.
В сравнении с ‘яйцами’
Сейчас wheel-формат более притягателен, чем egg. Его разработка активнее, PyPI начал добавлять его поддержку и, так как с ним начинают работать утилиты, он похож на лучшее решение. ‘Яйца’ пока что поддерживаются только easy_install, хотя большинство давно перешло на pip.
Итак, теперь он у вас есть. Python на колёсах. И это вроде даже работает, и, возможно, стоит потраченного времени.
Русские Блоги
Инструменты для упаковки и распространения Python
В этой статье в основном рассказывается о том, как упаковать и загрузить лично написанное приложение Python на официальный склад PyPI, чтобы его можно было устанавливать и использовать напрямую через pip и поддерживать в PyPI.
Распределение инструментов setuptools
Обычная установка Python идет с setuptools, если нет, вы можете использовать pip для установки:
setuptools прост и удобен в использовании, просто напишите короткий установочный файл setup.py, чтобы упаковать приложение Python.
Первый установочный файл
Создайте новый установочный файл setup.py в каталоге learn_setup, а затем создайте пакет myapp для имитации пакета с исходным кодом:
Содержимое простого файла setup.py выглядит следующим образом:
Создать колесо с установочным файлом
С помощью вышеуказанного файла setup.py мы можем открыть различные установочные пакеты, которые в основном делятся на две категории: sdist и bdist.
Source distribution
Использование sdist может быть упаковано в исходный дистрибутив, поддерживаемые форматы сжатия:
Format | Description | Notes |
---|---|---|
zip | zip file (.zip) | Windows по умолчанию |
gztar | gzip’ed tar file (.tar.gz) | Unix по умолчанию |
bztar | bzip2’ed tar file (.tar.bz2) | |
xztar | xz’ed tar file (.tar.xz) | |
ztar | compressed tar file (.tar.Z) | |
tar | tar file (.tar) |
Built distribution
Используя bdist, вы можете распечатать собранный дистрибутив. По сравнению с исходным пакетом, он быстрее устанавливается, потому что он предварительно собран:
Format | Description | Notes |
---|---|---|
gztar | gzipped tar file (.tar.gz) | Unix по умолчанию |
bztar | bzipped tar file (.tar.bz2) | |
xztar | xzipped tar file (.tar.xz) | |
ztar | compressed tar file (.tar.Z) | |
tar | tar file (.tar) | |
zip | zip file (.zip) | Windows по умолчанию |
rpm | RPM | |
pkgtool | Solaris pkgtool | |
sdux | HP-UX swinstall | |
wininst | self-extracting ZIP file for Windows | |
msi | Microsoft Installer. |
Чтобы упростить операцию, setuptools предоставляет следующие команды:
Command | Formats | Notes |
---|---|---|
bdist_dumb | tar, gztar, bztar, xztar, ztar, zip | Zip по умолчанию для Windows, gztar по умолчанию для Unix |
bdist_rpm | rpm, srpm | |
bdist_wininst | wininst | |
bdist_msi | msi |
Таким образом, вышеупомянутый пакет rpm может быть использован:
Если вы используете bdist_wininst, распечатывается установочный файл exe, вы можете нажать для установки.
Wheel
Преимущества колесного пакета:
Для упаковки с колесом сначала установите колесо:
Затем используйте bdist_wheel для упаковки:
Использование универсального также становится универсальным колесным пакетом, иначе его называют чистым колесным пакетом.
Установите колесо
Пример приложения в предыдущем разделе не имеет ничего. Далее добавьте модуль приветствия и переупаковки.
После повторной упаковки с помощью bdist_wheel, мы можем использовать pip для установки в локальный каталог сайтов-пакетов Python.
Теперь он используется так же, как и другие сторонние библиотеки, установленные с помощью pip:
Чтобы удалить, используйте pip uninstall 。
Загрузить Колесо в PyPI
Пакет Wheel можно использовать и передавать другим людям, но его обслуживание и обновление неудобно, а PyPI в качестве репозитория программного обеспечения Python позволяет каждому легко загружать и скачивать и управлять сторонней библиотекой.
Зарегистрировать учетную запись PyPI
авторизоваться https://pypi.python.org/pypiДля входа в учетную запись.
Установить шпагат
Хотя setuptools поддерживает использование setup.py upload Загружайте файлы пакетов в PyPI, но поддерживает только HTTP и заменяет новый шпагат.
Точно так же сначала нужно установить шпагат:
Загрузить с помощью шпагата
Просто введите пароль своей учетной записи, здесь настраиваются официальные pypi и pypitest, если вы хотите настроить другие склады, добавьте в соответствии с форматом.
Вернитесь на домашнюю страницу PyPI, чтобы увидеть загруженное firstApp.
При отображении домашней страницы PyPI будет задержка, поэтому результаты не могут быть найдены сразу, и поиск в pip может оказаться невозможным, но его можно установить с помощью pip.
Выше приведено все содержимое упаковки и распространения Python, конечно же, самая простая функция. Более сложные упаковки, такие как фильтрация модулей, не-py-упаковка файлов, информация об авторах и другие общие требования, реализованы в setup() Внутри. Поэтому следующим шагом является подробное описание setup ().
параметры настройки ()
В приведенном выше установочном файле setup.py мы использовали некоторые параметры setup (): имя, версия, пакеты.
version
Номер версии проекта, как правило, состоит из трех частей: ОСНОВНОЙ, МЕНЬШИЙ, ОБСЛУЖИВАНИЕ.
— MAJOR version when they make incompatible API changes,
— MINOR version when they add functionality in a backwards-compatible manner, and
— MAINTENANCE version when they make backwards-compatible bug fixes.
packages
Перечислите все пакеты, которые должны быть упакованы в проекте. Общего пользования setuptools.find_packages() Автоматическое обнаружение.
exclude Используется для исключения неупакованных пакетов.
description
Краткое описание проекта, обычно всего одно предложение, будет отображаться в нижней части имени на PyPI.
author
Информация об авторе.
license
Лицензия на проект.
Для введения и выбора различных лицензий, обратитесь к:https://choosealicense.com/。
classifiers
keywords
Список ключевых слов проекта.
project_urls
Дополнительные ссылки, связанные с проектом, такие как хранилище кода, адрес документа и т. Д.
install_requires
Библиотека Python, от которой зависит проект. При использовании pip для установки этого проекта он автоматически проверяет и устанавливает зависимости.
python_requires
Укажите версию Python, от которой зависит проект.
package_data
Проект зависит от файла данных. Файл данных должен быть размещен в каталоге проекта и использовать относительный путь.
Если вы не укажете, что ключ, используемый в качестве каталога, является пустой строкой, это означает, что он работает на всех модулях (в следующем примере будут включены все файлы yaml в каталоге данных в пакете):
data_files
Если файл данных существует за пределами проекта, им можно управлять с помощью параметра data_files или файла MANIFEST.in.
Если используется для колеса, используйте data_files.
Приведенные выше настройки добавят файл data / conf.yml в каталог mydata при упаковке колеса.
data_files не может использовать подстановочные знаки пути.
Кроме того, скрипты, py_modeles, entry_points, console_scripts и другие ссылки на параметры:https://packaging.python.org/tutorials/distributing-packages/#setup-args。
Другие файлы инициализации
При чтении библиотеки Python на Github, помимо основного файла setup.py и основной программы, вы также увидите некоторые другие файлы. В этом разделе будут представлены их роль и использование.
setup.cfg
Содержит некоторые параметры по умолчанию при сборке, такие как:
README.rst/README.md
Проектная документация, использованиеreStrutruedText Он может хорошо отображаться на PyPI, но Markdown не поддерживает его достаточно хорошо.
MANIFEST.in
Этот файл сообщает программе setuptools, какие дополнительные файлы необходимо упаковать при упаковке исходного пакета.
Выкладка python-проектов с помощью pip и wheel
Проблема
Каждый запускает проект по разному; для полноты картины коротко опишу что использую я.
В наших проектах мы частенько используем модули, которые в какой то мере написаны на C и требуют компиляции. Тут и начинаются неудобства: на сервере нужно установить компилятор и еще кучу dev пакетов, чтобы скомпилировать зависимости вашего проекта (таких как simplejson или lxml). Первое, что приходит в голову — это взять и скомпилировать локально, а потом просто скопировать на сервер. А что тут такого? И там и там x86_64. Но как оказалось бинарная совместимость это шаткое понятие в Linux системах. Я конечно догадываюсь почему это так, но слабоват чтобы об этом рассуждать. Короче, то что вы скомпилируете у себя на Ubuntu не обязательно будет работать на Debian. Если у вас куча серверов, можно выделить один для сборки пакетов или поднять идентичную виртуальную машину локально и компилировать там.
Попытка №1
Когда я занялся этим вопросом в первый раз, я пошел во все тяжкие. Я поднимал свой Debian репозиторий и собирал проект в нативные deb-пакеты. Все было вполне автоматизировано: я написал скрипты для автоматического запуска проекта; на fabric написал скрипт для сборки deb-пакетов и выкладки проекта на сервер. Проект разбивался на три разных deb-пакета: код проекта, virtualenv со всеми модулями, конфигурации (dev, prod). Установка и запуск на сервере заключалась в том, чтобы выполнить одну команду:
Попытка №2
Во второй раз, я решил что лучше собирать все нужные модули в отдельные бинарные пакеты. Наткнулся на относительно новый проект под названием wheel и решил попробовать.
Wheel — это альтернатива бинарным яйцам; автор старается делать все по последним веяниям, и не так давно его PEP был принят. Из отличий примечательно, что wheel это формат установки, а не импортируемое. Еще wheel хороший помощник при работе на локальной машине: можно скачать и скомпилировать все часто используемые пакеты в одну папку, потом при создании новой виртуальной среды устанавливать пакеты оттуда за O(1).
На стороне сервера остается только установить и запустить. Это выглядит примерно так:
Я пишу на Python 2.7.3, который стоит по умолчанию на моей Ubuntu, а на серверах стоит Debian и Python версии 2.6. Конечно же между ними есть разница, например: форматирование строк c помощью format нет на Python 2.6. Пытаться поставить 2.7.3 из дистрибутива не лучшая идея, легче скомпилировать Python и в этом нам хороший помощник — проект pythonbrew.
Лень — двигатель прогресса! Все мы программисты лентяи(особенно те, кто пишут на Python и Ruby) и, сталкиваясь с неудобствами, мы хотим сделать себе жизнь проще. А как делаете выкладку вы?
Python wheel что это
Войти
Авторизуясь в LiveJournal с помощью стороннего сервиса вы принимаете условия Пользовательского соглашения LiveJournal
Прикручиваем «колеса» (wheels) к Питону (Python) под Windows 7
Если формулировать заголовок менее «художественно», то в посте я собираюсь ответить на вопросы:
1. Что делать, если при установке библиотеки (пакета) Python происходит ошибка Unable to find vcvarsall.bat?
2. Можно ли перенести пакет, установленный в Anaconda в другую установку Python, например IDLE?
3. Как перенести библиотеку с одного ПК на другой (с некоторыми ограничениями)?
Итак, в 2015-м году (да, я добрался до папок типа «разобрать потом 4»!)) я нашел пример программы на Python, которая показывает MAC-адреса сетевых интерфейсов ПК, на котором она запущена. Все это решается 3-мя строчками кода буквально:
import netifaces
for i in netifaces.interfaces():
print (netifaces.ifaddresses(i)[netifaces.AF_L INK])
Работает все это, как не сложно понять, при помощи библиотеки netifaces. Если библиотека не установлена, то мы получим следующее сообщение:
ImportError: No module named ‘netifaces’
Дальнейший действия в Ubuntu просты. Выполняем:
Successfully installed netifaces
Cleaning up.
После этого можно вернуться в IDLE и снова выполнить программу. Работает!
А вот в Windows такой «номер» не пройдет.
Может быть поэтому довольно распространенным ответом на вопросы в сети «у меня не ставится такая-то библиотека под Windows» является предложение сменить ОС?)
Итак, начинаем пробовать. У меня установлена Anaconda помимо IDLE, поэтому запускаю pip не просто в командной строке (там сейчас Anaconda «главная»), а непосредственно из папки со скриптами:
error: Unable to find vcvarsall.bat
Пока разбирался с версиями, решил заодно и свой Python обновить до 3.5.
Скачать готовые «колеса» можно, например здесь и здесь. Ну а мне данный вариант подходит тем, что с его помощью я:
1. Упаковываю установленый в Anaconda пакет в файл *.whl:
Collecting netifaces
Using cached netifaces-0.10.5-cp35-cp35m-win_amd64.wh l
Saved c:\users\user\netifaces-0.10.5-cp35-cp35 m-win_amd64.whl
2. И устанавливаю. Я, чтобы ускорить процесс, положил файл в папку, в которой расположены скрипты IDLE. Запускаем установку. Не забываем про «волшебную» клавишу Tab, которая легко заканчивает имя файла (pip install ***.whl):
Получаем сообщение об успешной установке!
Если я что-то сделал неоптимально, или если вы знаете хорошие «хранилища колес», как обычно прошу вас комменитровать! А у меня на этом все.
UPD:
Случайно натолкнулся на любопытный перевод на Хабре по теме: Python на колёсах.
Алексей написал несколько развернутых комментариев под анонсом во «ВКонтакте», поэтому ссылка на него, чтобы не потерять.