Как создать файл setup py
Каждый разработчик ПО должен знать как создать библиотеку с нуля. В процессе работы Вы можете многому научиться. Только не забудьте запастись временем и терпением.
Может показаться, что создать библиотеку с открытым исходным кодом сложно, но Вам не нужно быть потрепанным жизнью ветераном своего дела, чтобы разобраться в коде. Также как Вам не нужна мудреная идея продукта. Но точно понадобятся настойчивость и время. Надеюсь, что данное руководство поможет Вам создать первый проект с минимальной затратой и первого, и второго.
В этой статье мы пошагово разберем процесс создания базовой библиотеки на Python. Не забудьте заменить в приведенном ниже коде my_package, my_file и т.п. нужными вам именами.
Шаг 1: Составьте план
Теперь, когда мы уже знаем, что хотим делать, нужно придумать название для библиотеки.
Шаг 2: Дайте имя библиотеке
Придумывать имена сложно. Они должны быть короткими, уникальными и запоминающимися. Также они должны быть написаны строчными буквами, без прочерков и прочих знаков препинания. Подчеркивание не рекомендуется. В процессе создания библиотеки убедитесь, что придуманное Вами имя доступно на GitHub, Google и PyPi.
Если Вы надеетесь и верите, что однажды Ваша библиотека получит 10000 звезд GitHub, то стоит проверить, доступно ли данное имя в социальных сетях. В данном примере я назову свою библиотеку notebookc, потому что это имя доступное, короткое и более-менее описывает суть моей задумки.
Шаг 3. Настройте среду
Убедитесь, что у вас установлены и настроены Python 3.7, GitHub и Homebrew. Если вам нужно что-то из этого, вот подробности:
Python
Скачайте Python 3.7 здесь и установите его.
GitHub
Если у вас нет учетной записи GitHub, перейдите по этой ссылке и оформите бесплатную подписку. Посмотрите, как установить и настроить Git здесь. Вам потребуется утилита командной строки. Перейдите по ссылкам, скачайте и установите все, что Вам понадобится, придумайте юзернейм и укажите электронную почту.
Homebrew
Homebrew — менеджер библиотек для Mac. Инструкции по установке найдете здесь.
Начиная с Python 3.6 рекомендуется использовать venv для создания виртуальной среды для разработки библиотек. Существует множество способов управления виртуальными средами с помощью Python и все они со временем изменяются. Можете ознакомиться с обсуждением здесь, но, как говорится, доверяй, но проверяй.
Начиная с версии Python 3.3 venv входит в систему по умолчанию. Обратите внимание, что venv устанавливает pip и setuptools начиная с Python 3.4.
Создайте виртуальную среду Python 3.7 с помощью следующей команды:
python3.7 -m venv my_env
Замените my_env вашим именем. Активируйте среду таким образом:
Теперь вы должны наблюдать (my_env) (или имя, которое вы выбрали для вашей виртуальной среды) в крайнем левом углу терминала.
Когда закончите работу, деактивируйте виртуальную среду с помощью deactivate .
Теперь давайте настроим GitHub.
Шаг 4: Создайте организацию в GitHub
GitHub — лидер на рынке реестров контроля версий. Еще две популярные опции — GitLab и Bitbucket. В данном гиде мы будем использовать именно GitHub.
Вам придется часто обращаться к Git и GitHub, поэтому если Вы не знакомы с системой, то можете обратиться к моей статье.
Создайте новую организацию в GitHub. Следуйте инструкциям. Я назвал свою организацию notebooktoall. Вы можете создать репозиторий под своей личной учетной записью, но одна из целей работы — научиться создавать проект с открытым исходным кодом для более широкого сообщества.
Шаг 5: Настройте GitHub Repo
Создайте новый репозиторий. Я назвал свой notebookc.
Добавьте .gitignore из выпадающего списка. Выберите Python для своего репозитория. Содержимое Вашего файла .gitignore будет соответствовать папкам и типам файлов, исключенным из вашего хранилища. Вы можете позже изменить .gitignore, чтобы исключить другие ненужные или конфиденциальные файлы.
Рекомендую выбрать лицензию в списке Выбрать лицензию. Она определяет, что могут делать пользователи Вашего репозитория. Одни лицензии позволяют больше других. Если Вы ничего не выбираете, то автоматически начинают действовать стандартные законы об авторских правах. Узнайте больше о лицензиях здесь.
Для этого проекта я выбрал третью версию Открытого лицензионного соглашения GNU, потому что она популярная, проверенная и “гарантирует пользователям свободу использования, изучения, обмена и изменения программного обеспечения” — источник.
Шаг 6: Клонируйте и добавьте директории
Выберите, куда Вы хотите клонировать Ваш репозиторий или выполните следующую функцию:
Подставьте свою организацию и репозиторий.
Перейдите в папку проекта с помощью десктопного графического интерфейса или редактора кода. Или используйте командную строку с cd my-project и после просмотрите файлы с ls —A .
Ваши исходные папки и файлы должны выглядеть так:
.git
.gitignore
LICENSE
README.rst
Создайте вложенную папку для основных файлов проекта. Я советую назвать ее так же, как и вашу библиотеку. Убедитесь, что в имени нет пробелов.
Создайте файл с именем __init__.py в основной вложенной папке. Этот файл пока останется пустым. Он необходим для импорта файлов.
Создайте еще один файл с таким же именем, как у основной вложенной папки, и добавьте .py. Мой файл называется notebookc.py. Вы можете назвать этот Python-файл как захотите. Пользователи библиотеки при импорте модуля будут ссылаться на имя этого файла.
Содержимое моей директории notebookc выглядит следующим образом:
.git
.gitignore
LICENSE
README.rst
notebookc/__init__.py
notebookc/notebookc.py
Шаг 7: Скачайте и установите requirements_dev.txt
На верхнем уровне директории проекта создайте файл requirements_dev.txt. Часто этот файл называют requirements.txt. Назвав его requirements_dev.txt, Вы показываете, что эти библиотеки могут устанавливаться только разработчиками проекта.
В файле укажите, что должны быть установлены pip и wheel.
Обратите внимание, что мы указываем точные версии библиотек с двойными знаками равенства и полными номерами версии.
Закрепите версии вашей библиотеку в requirements_dev.txt
Соавтор, который разветвляет репозиторий проекта и устанавливает закрепленные библиотеки require_dev.txt с помощью pip, будет иметь те же версии библиотеки, что и Вы. Вы знаете, что эта версия будет работать у них. Кроме того, Read The Docs будет использовать этот файл для установки библиотек при сборке документации.
В вашей активированной виртуальной среде установите библиотеку в файл needs_dev.txt с помощью следующей команды:
pip install -r requirements_dev.txt
Настоятельно рекомендую обновлять эти библиотеки по мере выхода новых версий. На данный момент установите любые последние версии, доступные на PyPi.
В следующей статье расскажу, как установить инструмент, облегчающий этот процесс. Подпишитесь, чтобы не пропустить.
Шаг 8: Поработайте с кодом
В целях демонстрации давайте создадим базовую функцию. Свою собственную крутую функцию сможете создать позже.
Вбейте следующее в Ваш основной файл (для меня это notebookc/notebookc/notebookc.py):
Вот наша функция во всей красе.
Строки документа начинаются и заканчиваются тремя последовательными двойными кавычками. Они будут использованы в следующей статье для автоматического создания документации.
Сохраните изменения. Если хотите освежить память о работе с Git, то можете заглянуть в эту статью.
Шаг 9: Создайте setup.py
Файл setup.py — это скрипт сборки для вашей библиотеки. Функция setup из Setuptools создаст библиотеку для загрузки в PyPI. Setuptools содержит информацию о вашей библиотеке, номере версии и о том, какие другие библиотеки требуются для пользователей.
Вот мой пример файла setup.py:
Обратите внимание, что long_description установлен на содержимое файла README.md. Список требований (requirements), указанный в setuptools.setup.install_requires, включает в себя все необходимые зависимости для работы вашей библиотеки.
В отличие от списка библиотек, требуемых для разработки в файле require_dev.txt, этот список должен быть максимально разрешающим. Узнайте почему здесь.
Ограничьте список install_requires только тем, что Вам надо — Вам не нужно, чтобы пользователи устанавливали лишние библиотеки. Обратите внимание, что необходимо только перечислить те библиотеки, которые не являются частью стандартной библиотеки Python. У Вашего пользователя и так будет установлен Python, если он будет использовать вашу библиотеку.
Наша библиотека не требует никаких внешних зависимостей, поэтому Вы можете исключить четыре библиотеки, перечисленных в примере выше.
Соавтор, который разветвляет репозиторий проекта и устанавливает закрепленные библиотеки с помощью pip, будет иметь те же версии, что и Вы. Это значит, что они должны работать.
Измените информацию setuptools так, чтобы она соответствовала информации вашей библиотеки. Существует множество других необязательных аргументов и классификаторов ключевых слов — см. перечень здесь. Более подробные руководства по setup.py можно найти здесь и здесь.
Сохраните свой код в локальном репозитории Git. Пора переходить к созданию библиотеки!
Шаг 10: Соберите первую версию
Twine — это набор утилит для безопасной публикации библиотек Python на PyPI. Добавьте библиотеку Twine в следующую пустую строку файла require_dev.txt таким образом:
Затем закрепите Twine в Вашей виртуальной среде, переустановив библиотеки needs_dev.txt.
Затем выполните следующую команду, чтобы создать файлы библиотеки:
Необходимо создать несколько скрытых папок: dist, build и — в моем случае — notebookc.egg-info. Давайте посмотрим на файлы в папке dist. Файл .whl — это файл Wheel — встроенный дистрибутив. Файл .tar.gz является исходным архивом.
На компьютере пользователя pip будет по мере возможности устанавливать библиотеки как wheels/колеса. Они устанавливаются быстрее. Когда pip не может этого сделать, он возвращается к исходному архиву.
Давайте подготовимся к загрузке нашего колеса и исходного архива.
Шаг 11: Создайте учётную запись TestPyPI
PyPI — каталог библиотек Python (Python Package Index). Это официальный менеджер библиотек Python. Если файлы не установлены локально, pip получает их оттуда.
TestPyPI — это работающая тестовая версия PyPI. Создайте здесь учетную запись TestPyPI и подтвердите адрес электронной почты. Обратите внимание, что у Вас должны быть отдельные пароли для загрузки на тестовый сайт и официальный сайт.
Шаг 12: Опубликуйте библиотеку в PyPI
Используйте Twine для безопасной публикации вашей библиотеки в TestPyPI. Введите следующую команду — никаких изменений не требуется.
Вам будет предложено ввести имя пользователя и пароль. Не забывайте, что TestPyPI и PyPI имеют разные пароли!
При необходимости исправьте все ошибки, создайте новый номер версии в файле setup.py и удалите старые артефакты сборки: папки build, dist и egg. Перестройте задачу с помощью python setup.py sdist bdist_wheel и повторно загрузите с помощью Twine. Наличие номеров версий в TestPyPI, которые ничего не значат, особой роли не играют — Вы единственный, кто будет использовать эти версии библиотек.
После того, как Вы успешно загрузили свою библиотеку, давайте удостоверимся, что Вы можете установить его и использовать.
Шаг 13: Проверьте и используйте установленную библиотеку
Создайте еще одну вкладку в командном интерпретаторе и запустите другую виртуальную среду.
Если Вы уже загрузили свою библиотеку на официальный сайт PyPI, то сможете выполнить команду pip install your-package . Мы можем извлечь библиотеку из TestPyPI и установить его с помощью измененной команды.
Вот официальные инструкции по установке вашей библиотеки из TestPyPI:
Вы можете заставить pip загружать библиотеки из TestPyPI вместо PyPI, указав это в index-url.
Если хотите, чтобы pip также извлекал и другие библиотеки из PyPI, Вы можете добавить — extra-index-url для указания на PyPI. Это полезно, когда тестируемая библиотека имеет зависимости:
Если у вашей библиотеки есть зависимости, используйте вторую команду и подставьте имя вашей библиотеки.
Вы должны увидеть последнюю версию библиотеки, установленного в Вашей виртуальной среде.
Чтобы убедиться, что Вы можете использовать свою библиотеку, запустите сеанс IPython в терминале следующим образом:
Импортируйте свою функцию и вызовите ее со строковым аргументом. Вот как выглядит мой код:
После я получаю следующий вывод:
(Когда-нибудь я конвертирую для тебя блокнот, Джефф)
Шаг 14: Залейте код на PyPI
Залейте Ваш код на настоящий сайт PyPI, чтобы люди могли скачать его с помощью pip install my_package .
Загрузить код можно так:
Обратите внимание, что Вам нужно обновить номер версии в setup.py, если Вы хотите залить новую версию в PyPI.
Отлично, теперь давайте загрузим нашу работу на GitHub.
Шаг 15: Залейте библиотеку на GitHub
Убедитесь, что Ваш код сохранен.
Моя папка проекта notebookc выглядит так:
Исключите любые виртуальные среды, которые Вы не хотите загружать. Файл Python .gitignore, который мы выбрали при создании репозитория, не должен допускать индексации артефактов сборки. Возможно, Вам придется удалить папки виртуальной среды.
Переместите вашу локальную ветку на GitHub с помощью git push origin my_branch .
Шаг 16: Создайте и объедините PR
В браузере перейдите к GitHub. У Вас должна появиться опция сделать pull-запрос. Нажимайте на зеленые кнопки, чтобы создать, объединить PR и чтобы убрать удаленную ветку.
Вернувшись в терминал, удалите локальную ветку с git branch -d my_feature_branch .
Шаг 17: Обновите рабочую версию на GitHub
Создайте новую версию библиотеки на GitHub, кликнув на релизы на главной странице репозитория. Введите необходимую информацию о релизе и сохраните.
На сегодня достаточно!
Мы научимся добавлять другие файлы и папки в будущих статьях.
А пока давайте повторим шаги, которые мы разобрали.
Итог: 17 шагов к рабочей библиотеке
- Составьте план.
- Дайте имя библиотеке.
- Настройте среду.
- Создайте организацию в GitHub.
- Настройте GitHub Repo.
- Клонируйте и добавьте директории.
- Скачайте и установите requirements_dev.txt.
- Поработайте с кодом.
- Создайте setup.py.
- Соберите первую версию.
- Создайте учётную запись TestPyPI.
- Опубликуйте библиотеку в PyPI.
- Проверьте и используйте установленную библиотеку.
- Залейте код на PyPI.
- Залейте библиотеку на GitHub.
- Создайте и объедините PR.
- Обновите рабочую версию на GitHub.
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
Python - замечательный язык программирования. Одной из самых слабых его сторон является пакеты. Это общеизвестный факт в сообществе. Установка, импорт, использование и создание пакетов улучшилась с годами, но она по-прежнему не соответствует новым языкам, таким как Go и Rust, которые могут многому научиться из-за проблем Python и других более зрелых языков.
В этом уроке вы узнаете все, что вам нужно знать, чтобы создавать и делиться своими собственными пакетами. Для общей информации о пакетах Python ознакомьтесь с разделом «Как использовать пакеты Python».
Упаковка проекта
Упаковка проекта - это процесс, с помощью которого вы берете надежно согласованный набор модулей Python и, возможно, других файлов и помещаете их в структуру, которую можно легко использовать. Существуют различные вещи, которые вы должны учитывать, такие как зависимости от других пакетов, внутренняя структура (подпакеты), управление версиями, целевая аудитория и форма пакета (исходный код и/или двоичный файл).
Пример
Начнем с быстрого примера. Пакет conman представляет собой пакет для управления конфигурацией. Он поддерживает несколько форматов файлов, а также распределенную конфигурацию с помощью etcd.
Содержимое пакета обычно хранится в одной директории (хотя обычно для разделения подпакетов в нескольких каталогах), а иногда, как и в этом случае, в собственном репозитории git.
Корневой каталог содержит различные файлы конфигурации ( setup.py является обязательным и наиболее важным), а сам код пакета обычно находится в подкаталоге, имя которого является именем пакета и в идеале является каталогом тестов. Вот как это выглядит для «conman»:
Давайте быстро заглянем в файл setup.py. Он импортирует две функции из пакета setuptools: setup() и find_packages() . Затем он вызывает функцию setup() и использует find_packages() для одного из параметров.
Это довольно нормально. Хотя файл setup.py является обычным файлом Python, и вы можете делать все, что хотите, его основное задание - вызвать функцию setup() с соответствующими параметрами, поскольку он будет запускаться различными инструментами стандартным способом при установке вашего пакета. Я расскажу подробности в следующем разделе.
Файлы конфигурации
В дополнение к setup.py есть еще несколько дополнительных файлов конфигурации, которые могут отображаться здесь и обслуживать различные цели.
Setup.py
Функция setup() принимает большое количество именованных аргументов для управления многими аспектами установки пакета, а также для запуска различных команд. Многие аргументы указывают метаданные, используемые для поиска и фильтрации при загрузке вашего пакета в репозиторий.
- name: имя вашего пакета (и как оно будет указано в PYPI)
- version: это важно для поддержания правильного управления зависимостями
- url: URL вашего пакета, обычно GitHub или URL-адрес readthedocs
- packages: список подпакетов, которые необходимо включить; здесь помогает find_packages()
- setup_requires: здесь вы указываете зависимости
- test_suite: какой инструмент запускается во время тестирования
long_description устанавливается здесь на содержимое файла README.md , что является наилучшей практикой для использования одного источника правды.
setup.cfg
Файл setup.py также поддерживает интерфейс командной строки для запуска различных команд. Например, чтобы запустить модульные тесты, вы можете ввести: python setup.py test
Файл setup.cfg является файлом формата ini, который может содержать параметры по умолчанию для команд, которые вы передаете setup.py . Здесь setup.cfg содержит некоторые опции для nosetests (наш тестовый раннер):
MANIFEST.in
Этот файл содержит файлы, которые не являются частью внутреннего каталога пакетов, но вы все еще хотите включить его. Обычно это файл readme , файл лицензи Важным файлом является файл requirements.txt . Этот файл используется pip для установки других необходимых пакетов.
Вот файл MANIFEST.in в conman:
Зависимости
Вы можете указать зависимости как в разделе install_requires файла setup.py , так и в файле requirements.txt . Pip установит автоматически зависимости от install_requires , но не из файла requirements.txt . Чтобы установить эти требования, вам нужно будет указать его явно при запуске pip install -r requirements.txt .
Параметр install_requires предназначен для указания минимальных и более абстрактных требований на основном уровне версии. Файл requirements.txt предназначен для более конкретных требований, часто с привязкой к второстепенным версиям.
Вот файл требований conman. Вы можете видеть, что все версии зафиксированы, что означает, что это может негативно повлиять, если один из этих пакетов обновится и внесет изменения, которые ломают conman.
Пиннинг дает вам предсказуемость и спокойствие. Это особенно важно, если многие люди устанавливают ваш пакет в разное время. Без закрепления каждый человек получит различное сочетание версий зависимостей на основе того, когда они его установили. Недостатком пиннинга является то, что если вы не справляетесь с развитием зависимостей, вы можете застрять на старой, плохо исполняющейся и даже уязвимой версии некоторой зависимости.
Я изначально написал conman в 2014 году и не обращал на него особого внимания. Теперь для этого урока я обновил все, и для почти каждой зависимости были некоторые существенные улучшения.
Распределения
Вы можете создать дистрибутив источника или бинарный дистрибутив. Я расскажу об обоих.
Распределение источников
Вы создаете исходный дистрибутив с помощью команды: python setup.py sdist . Вот вывод для conman:
Как вы можете видеть, я получил одно предупреждение о том, что отсутствует файл README с одним из стандартных префиксов, потому что мне нравится Markdown, поэтому вместо этого у меня есть «README.md». Кроме этого, все исходные файлы пакета были включены и дополнительные файлы. Затем в каталоге conman.egg-info была создана куча метаданных. Наконец, создается сжатый tar-архив под названием conman-0.3.tar.gz и помещается в подкаталог dist .
Для установки этого пакета потребуется шаг сборки (хотя это чистый Python). Вы можете установить его с помощью pip, просто передав путь к пакету. Например:
Conman был установлен в site-packages и может быть импортирован как любой другой пакет:
Wheels
Wheels - относительно новый способ упаковки кода Python и, возможно, C-расширений. Они заменяют формат egg. Существует несколько типов колес: чистые колеса Python, платформы и универсальные колеса. Чистые колеса Python - это пакеты, такие как conman, у которых нет кода расширения C.
Платформенные колеса имеют код расширения C. Универсальные колеса - это чистые колеса Python, которые совместимы как с Python 2, так и с Python 3 с одинаковой базой кода (они не требуют даже 2to3). Если у вас есть чистый пакет Python и вы хотите, чтобы ваш пакет поддерживал как Python 2, так и Python 3 (становится все более и более важным), вы можете создать единую универсальную сборку вместо одного колеса для Python 2 и одного колеса для Python 3.
Если в вашем пакете есть код расширения C, вы должны создать колесо платформы для каждой платформы. Огромное преимущество колес, особенно для пакетов с расширениями C, заключается в том, что нет необходимости иметь компилятор и поддерживающие библиотеки, доступные на целевой машине. Колесо уже содержит встроенный пакет. Таким образом, вы знаете, что его гораздо быстрее установить, потому что это буквально просто копия. Люди, которые используют научные библиотеки, такие как Numpy и Pandas, действительно могут это оценить, поскольку установка таких пакетов требует много времени и может быть неудачной, если какая-то библиотека отсутствует или компилятор не настроен должным образом.
Команда для создания чистых или платформенных колес: python setup.py bdist_wheel .
Setuptools - движок, который обеспечивает функцию setup() , будет автоматически обнаруживаться, если требуется чистое или платформенное колесо.
При проверке каталога dist вы можете увидеть, что было создано чистое колесо Python:
Название «conman-0.3-py2-none-any.whl» имеет несколько компонентов: имя пакета, версию пакета, версию Python, версию платформы и, наконец, расширение «whl».
Чтобы создавать универсальные пакеты, вы просто добавляете --universal , как в python setup.py bdist_wheel --universal .
Полученное колесо называется "conman-0.3-py2.py3-none-any.whl".
Обратите внимание, что вы несете ответственность за то, чтобы ваш код действительно работал как с Python 2, так и с Python 3, если вы создаете универсальный пакет.
Заключение
Написание собственных пакетов Python требует использования большого количества инструментов, определения большого количества метаданных и тщательного анализа ваших зависимостей и целевой аудитории. Но награда велика.
Если вы правильно напишите полезный код и упакуете его, люди смогут легко его установить и извлечь из него выгоду.
Структура пакета
Сборка пакета
Более подробно об этом файле можно прочитать в документации.
Указываем зависимости
Для того, чтобы с пакетом можно было работать сразу после установки, вы должны указать в его конфигурации, от каких пакетов он зависит, чтобы они были сразу же установлены. Нужно просто вставить ‘install_requires=[…]’ в функцию setup. Можно также задать версию зависимости:
Дополнительные файлы
Иногда бывает необходимость вложить в пакет другие типы файлов. Для этого:
- Задайте ‘include_package_data=True’
- Создайте файл MANIFEST.in в папке с setup.py
- Добавьте путь до файла в MANIFEST как ‘include /path/to/test.json’, путь при этом относительный. Также можно использовать поисковый шаблон типа ‘*.json’.
Сборка
Теперь у нас всё готово, приступаем к сборке пакета. Это значит, что мы создадим дистрибутив исходного кода (напр., tar.gz) или бинарный файл (напр., wheel). Это очень просто.
В результате у нас в папке ‘./dist’ появятся оба формата. при этом имя дистрибутива будет присвоено исходя из имени пакета и его версии.
Распространение пакета
Поздравляю, вы создали замечательный пакет! Теперь необходимо выложить его для общего доступа. Мы загрузим его на Pypi, поэтому в будущем можно будет его установить командой ‘pip install’.
Для начала создайте учётную запись на сайте pypi.
При этом файлы из папки ‘dist/’ выгрузятся в каталог pypi. Также вы можете явно указать только определённый файл для выгрузки. Twine это специальная утилита для работы с pypi. При первой загрузке пакета она зарегистрирует пакет в pypi.
Работа с пакетом
Теперь ваш пакет опубликован в pypi. Для его установки достаточно набрать ‘pip install my_package’, а затем в коде ‘import my_package’.
При локальной разработке пакета для его тестирования добавьте путь к нему в $PYTHONPATH. Но если вы не хотите трогать переменные окружения, установите его командой ‘pip install -e .’ из папки с пакетом.
Одна из действительно полезных вещей в python — это система скриптов установки. Любой, серьезно увлекающийся python-программированием разработчик рано или поздно сталкивается с ней. Но из-за гибкости инструментария скриптов установки, их документация весьма раздута. На текущий момент имеется набор утилит (setuptools, distutils, distribute) выполняющих одинаковые задачи.
В данной статье я на конкретных примерах покажу как создать и настроить простой python-пакет.
Наш проект будет иметь следующую функциональность:
- Метод возвращающий строку: "Hello World!";
- Команда helloworld печатающая эту строку в стандартный вывод.
Создаем структуру проекта
Для начала создадим директорию для пакета. Ее минимальный набор файлов состоит из: файла дистрибьюции ( setup.py ) описывающего метаданные и python кода проекта (в нашем случае модуля helloworld).
Также, xорошим тоном считается создание в корне директории файла с описанием проекта: README.txt .
Получаем следующую структуру:
Наша корневая директория helloworld-project будет содержать мета-данные пакета и вспомогательные файлы (тесты, лицензию, документацию и т.д.), а поддиректория helloworld непосредственно сам модуль helloworld .
Теперь отредактируем файл: helloworld/core.py и добавим логику нашего приложения (получение и вывод строки "Hello World!"):
Редактируем мета-информацию (setup.py)
Заполним файл описания README.rst :
Теперь отредактируем файл setup.py :
Убедитесь, что в вашей системе доступны setuptools, в противном случае установите python-пакет distribute
Этих операций достаточно, чтобы собрать пакет дистрибьюции. Выполните команду сборки:
В случае успеха вы получите файл: dist/helloworld-1.0.tar.gz . Это полноценный, архивированный python-пакет и вы можете распространять его среди прочих разработчиков.
Виртуальное окружение
Virtualenv — пакет применяемый для создания изолированного python-окружения. Используем его для тестирования нашего проекта.
Создадим окружение env:
Команда создаст директорию env внутри нашего проекта и установит туда python, pip и distribute. Произведем в него установку нашего проекта.
И протестируем его работоспособность:
Все работает. Осталось добавить поддержку команды helloworld в консоли.
Создание команд
Для создания команды helloworld изменим файл setup.py :
В параметре entry_points мы задаем словарь с "точками вызова" нашего приложения. Ключ console_scripts задает список создаваемых исполняемых скриптов (в Windows это будут exe-файлы). В данном случае мы указали создание исполняемого скрипта helloworld при вызове которого будет запускаться метод print_message из модуля helloworld.core.
Переустановим модуль в наше окружение и проверим работу созданного скрипта (для этого прийдется активировать наше окружение):
Похоже все работает.
Работа с версиями
Номер версии важная часть любого проекта. От него зависит обновление пакетов и разрешение зависимостей. В примере выше мы указали номер версии 1.0 в файле setup.py . Более правильное решение перенести его в файл helloworld/__init__.py чтобы сделать доступным в python-коде. По существующим соглашения для хранения номера версии в модуле, используется переменная __version__.
Изменим файл setup.py , чтобы нам не приходилось редактировать номер версии в двух местах:
Существует множество систем наименования версий в python обычно рекомендуется использовать PEP386. Можно представить, что обозначение версии состоит из номера мажорного, минорного релизов (номера багфикса при необходимости), разделенных точками. В последней части версии разрешается использовать буквы латинского алфавита. Примеры из официальной документации:
Управление зависимостями
Добавим функциональности нашему проекту. Создадим команду serve которая будет запускать вебсервер отдающий страницу со строкой "Hello world!" генерируемой нашим модулем. Для этого воспользуемся пакетом Flask.
Добавляем файл helloworld/web.py :
И файл helloworld/templates/index.html :
И опишем команду serve в файле setup.py :
Теперь в нашем проекте появилась зависимость от пакета Flask. Без его установки наше приложение не будет правильно работать. За описание зависимостей в файле setup.py отвечает параметр install_requires:
Проверим установку зависимостей обновив наш пакет и работу команды serve:
Управление файлами проекта (MANIFEST.in)
На текущий момент при сборке нашего пакета distutils включает в него только python-файлы. Необходимо включить в него файл helloworld/templates/index.html без которого проект работать не будет.
Чтобы сделать это мы должны сообщить distutils какие еще файлы надо включать в наш проект. Один из способов — это создание файла MANIFEST.in :
Данная команда указывает distutils на включение в проект всех html файлов в директории helloworld/templates .
Также придется обновить setup.py :
Теперь шаблоны будут включены в наш проект.
Создание и запуск тестов
Хорошей практикой считается создание тестов для вашего проекта. Добавим простейшую реализацию, файл tests.py :
И обновим setup.py :
Теперь мы можем произвести предварительное тестирование нашего проекта:
Обратите внимание, что для запуска тестов даже не нужно создание виртуального окружения. Необходимые зависимости будут скачаны в директорию проекта в виде egg пакетов.
Прежде чем вы сможете опубликовать свой проект вам необходимо зарегистрироваться на PyPi. Запишите ваши реквизиты в файле
Все ваш проект готов к публикации. Достаточно ввести соответствующую команду:
Вы не сможете опубликовать пакет helloworld , тк данное имя проекта уже занято.
Python стал одним из самых широко используемых языков программирования. Главным образом объясняется это тем, что мы, его обычные пользователи, можем поделиться своим кодом, обеспечивая другим возможность беспрепятственно им пользоваться. А сделать это можно общепринятым способом, упаковав весь код и загрузив его в каталог программного обеспечения Python (Python Package Index или PyPI), с помощью которого пользователи легко и просто установят ваш пакет, используя инструмент pip.
Если у вас был опыт публикации пакета Python, то вы уже знаете, насколько всё просто. Однако новичкам этот процесс ошибочно представляется геркулесовым трудом. В данной статье будут рассмотрены все этапы подготовки пакета и его последующей публикации.
Очевидно, что на первом этапе ваша задача — завершить проект. Однако все понимают, что пакеты никогда не бывают идеальными. Поэтому не будем ждать окончания проекта, а заранее узнаем, как опубликовать пакет.
Для работы с текущим руководством представим, что директория со всеми файлами Python, включая нужный нам python_file_0.py , называется test_package . Именно этот пакет мы и намерены опубликовать. Следуя принципу простоты, файл python_file_0.py содержит лишь следующий код, который будет использован по мере нашей готовности импортировать пакет после его публикации:
1. Подготовка файлов
Перед тем, как углубиться в детали публикации, сначала структурируем директорию с помощью необходимых вспомогательных файлов. Ниже представлена файловая структура пакета:
- В корневой директории на одном уровне с test_package создайте файл README.md . Он будет содержать необходимую пользователям информацию о пакете, например сведения об установке и инструкции по применению.
- На этом же уровне находится файл setup.py . Он будет включать информацию, необходимую для подготовки пакета к публикации. Вскоре мы рассмотрим содержимое этого файла.
- В директории test_package создайте файл __init__.py именно с таким именем. Он трансформирует обычную директорию в пакет Python. Для этого простого пакета просто поместим код в python_file_0.py и экспортируем from test_package.python_file_0 import hello_world .
Файл README
Теоретически для этого файла можно использовать простой текст, но отдав предпочтение файлу Markdown, вы получите разные возможности форматирования и таким образом сделаете его более интересным для чтения. Ниже показан пример простого файла README.md :
Обратите внимание, что основное содержание сохраняется как файл TXT, показывающий исходный текст для Markdown, перед тем как Github автоматически применит форматирование для файлов Markdown.
Как правило, рекомендуется включать информацию о лицензии пакета, чтобы пользователи знали условия его использования. В нашем случае просто укажем лицензию MIT.
Файл setup
Как уже ранее упоминалось, файл setup.py нужен для того, чтобы указать способ подготовки пакета. Стандартный setup.py выглядит следующим образом:
- Сначала мы импортируем модуль setuptools , содержащий удобные методы настройки упаковки.
- В вызове функции setup() большинство параметров очень простые и не требуют пояснений. Рассмотрим основные моменты:
long_description . Из файла README.md обычно устанавливается подробное описание. Для его корректного отображения вы указываете, что это файл Markdown, задавая параметр long_description_content_type .
packages . Перечень пакетов, подлежащих публикации в пакете дистрибутива. Поскольку мы публикуем только один пакет test_package , то в списке значится именно его имя. Однако если вы планируете опубликовать все пакеты директории, то для удобства их извлечения используйте setuptools.find_packages() .
python_requires . Указывает необходимую для пакета версию Python.
2. Подготовка к загрузке
Создание API-токена
После регистрации аккаунта рекомендуется создать API-токен для загрузки пакета. Перейдите в раздел API tokens в настройках и кликните “Add API token.”
Следуйте инструкциям, чтобы создать API-токен. Укажите его область действия (scope) применительно к конкретным или ко всем проектам. После этого важно сохранить токен, чтобы впоследствии можно было к нему вернуться, поскольку в целях безопасности нельзя пересоздавать или восстанавливать уже существующий токен.
Установка инструментов архивации и загрузки
Надо сказать, что для архивации и загрузки пакетов Python существуют различные инструменты. Мы задействуем те из них, которые чаще всего используются для дистрибуции: setuptools , wheel и twine .
Если они не установлены на вашем компьютере, просто выполните следующую команду, и все три пакета с их зависимостями окажутся в вашем распоряжении.
3. Дистрибуция пакета
Архивация пакета
Архивация — первый этап подготовки пакета к дистрибуции. В терминале перейдите в корневую директорию, содержащую все файлы пакета, например setup.py , и выполните следующую команду:
Эта команда задействует инструмент wheel, который использует подробную инструкцию, содержащуюся в setup.py , для создания всех необходимых для дистрибуции файлов. Ниже представлена структура файла после архивации.
В частности, как показано выше, в директории dist он создаст два ключевых файла, готовых к загрузке.
Загрузка пакета
Процесс загрузки пакета в PyPI довольно простой. Еще раз отметим, что мы используем тестовый сайт, принцип работы с которым ничем не отличается от основного аналога. Используем уже имеющийся у нас инструмент twine , выполнив следующую команду в терминале:
По сути, эта команда запрашивает загрузку файлов из директории dist в репозиторий TestPyPI для дистрибуции. Вам предложат ввести имя пользователя и пароль, что является нормой при загрузке в PyPI. Но в целях безопасности будет лучше использовать в качестве имени __token__ , а в качестве пароля — ранее созданный токен.
Если всё сделано правильно, то загрузка пакета пройдет гладко. Однако в случае возникновения каких-либо сложностей, в файле setup.py обычно предоставляется подробная информация о возможных ошибках. Исправив их, вы сможете двигаться дальше.
4. Тестирование пакета
Просмотр пакета на PyPI
Импорт пакета
На этом же сайте вам предоставляется командная строка для установки тестового пакета. Просто скопируйте и вставьте в терминал:
С установкой этого пакета у вас не должно возникнуть сложностей. Настало время проверить, сможем ли мы его использовать, поскольку после загрузки пакета в репозиторий PyPI он считается общедоступным. Далее представлен импорт тестового пакета:
Как видно из примера, нам удалось использовать пакет, загруженный в PyPI для дистрибуции. Отличный результат!
Читайте также: