Рубрики
Без рубрики

Распределение пакетов Python может быть простым

Было так много постов в блоге и презентаций о упаковке Python, что я не хочу WRI … Tagged Python, Productivity, Architecture, Django.

Было так Многие сообщения в блоге и презентации о упаковке Python что я не хочу писать то, что можно интерпретировать как Еще один , но я попробую. Почему? Потому что до недавнего времени я работал над несколькими взаимосвязанными библиотеками, каждая из которых имел более нелепые процесс сборки, чем в следующем.

Само собой разумеется, у каждого была своя процедура развертывания. Некоторые были задокументированы, другие были оставлены в интерпретации автора. Десятки команд для выполнения. Некоторые должны были быть построены на месте, потому что CI, по -видимому, был «слишком низким по ресурсам». Все это для Pure Python Packages. Нет расширения C. Это все равно, что сказать «у нашей машины нет ресурсов для создания zip -файла».

Не говоря уже о библиотеках, которые сами перечислили как зависимости от строительства, или setup.py Чтение переменных среды виртуальной среды, чтобы определить, какая версия конкретной зависимости должна быть установлена. Или GIT ветвясь рабочими процессами, настолько сложными, что заставило разрешение слияния конфликтует рутину, причем претендент на изменение является худшим из них.

Если вы прагматичный разработчик, у которого есть лучшее, что связано со своим временем, чем просмотр сломанных процессов в действии, вы бы искали лучший способ. И вы бы нашли один после быстрого поиска и нескольких кликов мыши, потому что эти проблемы уже были решены и решены сообществом.

Резюме

Когда я начал искать решение, я хотел достичь трех вещей:

  1. Иметь одну команду для выполнения всех проверок достоверности пакета: сборка, тестовый набор, личинка, документация и т. Д.
  2. Иметь одну команду для развертывания, где разработчик указывает следующую версию, и она волшебным образом появляется на PYPI;
  3. Сделайте вышеупомянутые процессы легко отлаживать, изменить и заменить, если появится лучший вариант.

Это привело меня к Токс , инструмент автоматизации, в основном используемый для запуска тестовых наборов против нескольких версий зависимостей. Тем не менее, это также полезно для автоматизации всех видов различных задач, даже те, которые требуют Python 3, когда вы все еще используете Python 2. Чтобы дать вам вкус, куда это ведет, были достигнуты следующие вещи:

  1. Испытательный набор был выполнен против установленного распределения и несколько версий зависимостей, что обеспечивает действительное распределение, и вы поддерживаете несколько версий ваших зависимостей. Это достигается путем выполнения Токс В командной строке запустить весь набор тестов, или tox -e Если вы хотите проверить конкретный случай использования.
  2. Когда кто -то хочет создать новый релиз, нужно выполнить Tox -e Release Чтобы создать выпуск функции, или Tox -e Release -Patch Чтобы создать релиз патча, когда Семантическое управление версией используется. Процесс выпуска состоит из нескольких других Токс процессы, такие как изменение или Манифест , каждый из которых может быть выполнен индивидуально.
  3. Развертывание было выполнено в среде CI, но оно также может быть выполнено на месте. Это гарантировало, что распределения создаются в контролируемой и стабильной среде, а не на чьей -то машине с некоторыми случайными настройками.

Этот процесс был распространен в другие пакеты и во внутренний CookieCutter Проект, чтобы сделать его доступным для новых пакетов. Это означает, что разработчики имели единый, стандартизированный рабочий процесс, который позволил каждому инициировать новый релиз почти мгновенно, только чтобы он появился на PYPI за считанные минуты.

Этот пост обобет мой опыт и укажет вам на другие полезные посты, охватывающие этот предмет, чтобы вы не тратили время на одни и те же проблемы. Я избавлю вас от сложных деталей производства пакета, так как на этой теме уже достаточно материала.

Однако, если вам нужна ссылка, в которой все уже конфигурируется, посмотрите на Центральная линия упаковка. Я создал этот пакет во время колледжа в качестве упражнения, но в настоящее время я использую его в основном для тестирования упаковки и распространения. Основные файлы, на которых вы должны сосредоточиться, – setup.cfg , pyproject.toml , .bumpversion.cfg , .travis.yml и, наконец, что не менее важно, tox.ini Анкет

Немного истории

У Python довольно сложный механизм сборки и распределения, когда речь заходит о сторонних библиотеках. Это не ракетостроение, просто большое количество наследия, которое вы должны ориентироваться. Первоначальная идея состояла в том, чтобы иметь батареи включены Подход, где ядро Python имело все, что вам когда -либо понадобилось.

Однако этот процесс ингибировал повторное использование кода, который считался полезным, но недостаточно полезным, чтобы быть включенным в ядро Python. И так Pypi родился, место, где люди могли загрузить свой код Python и поделиться им с миром. Теперь у вас есть лучшее из обоих миров, верно?

Ну да и нет. Оглядываясь назад, легко критиковать решения, которые были приняты в то время, которые привели нас к моменту, когда у нас есть Несколько способов построения и распространения библиотек и Позвоните стандартной библиотеке Python в тупик Анкет Дело в том, что, хотя все не идеально, нет смысла жаловаться на это, если вы ничего не собираетесь делать с этим.

Чтобы исправить ход всей экосистемы Python, необходимо большое количество времени, энергии и денег. Это то, что сообщество с открытым исходным кодом традиционно мало, но Вещи улучшаются Анкет

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

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

Имея это в виду, я хотел бы представить вам один из способов, которые помогли нам разрешить наши различия и позволили нам преодолеть полуавтоматическую фазу. Важно отметить, что это не путь. Если это не подходит вам или вашей команде, хорошо. Это также не будет обвинять в упаковочной экосистеме, но показывает вам подход, который улучшил сотрудничество в различных библиотеках, внедрив следующие изменения:

  • Переход на SRC/макет
  • Декларативная конфигурация
  • Разработка на основе багажника
  • Управление изменением и версией
  • Выпуск автоматизации

Схема SRC

При работе с библиотеками Python, которые иногда называют пакетами (то есть каталогом с файлом __init__.py ), потому что они в основном состоят из пакетов, которые необходимо распределить, существуют два наиболее широких способа организации вашей кодовой базы:

  1. Площадь имен -пространство (Я не уверен, что это правильный термин, но давайте пока пойдем с ним):
├── mypackage
│ ├── __init__.py
│ └── mod1.py
├── tests
├── setup.py
└── setup.cfg

  1. SRC/ макеты :
├── src
│ └── mypackage
│ ├── __init__.py
│ └── mod1.py
├── tests
├── setup.py
└── setup.cfg

Вам может быть интересно, в чем разница? Разница в том, как Python’s Импорт Система обрабатывает эти файлы во время разработки и тестирования, и это влияет на процессы сборки и распределения.

Режим разработки

Прежде чем мы вступим в подробности, имейте в виду, что некоторые люди используют Symlinks для подключения пакетов к проектам, где они используются, тогда как другие используют Режим разработки включен пип S редактируемые установки Анкет Я лично предпочитаю последнее, что идет в соответствии с этим:

$ mkproject centerline # provided by `virtualenvwrapper`
$ git clone https://github.com/fitodic/centerline .
$ pip install -e .[dev,test,docs]

Почему я предпочитаю это? Потому что по моему опыту, это самый стабильный и надежный подход к разработке при разработке и распространении пакетов. Это также резко упрощает настройку пакета, как в тестировании, так и в производственных средах.

С другой стороны, я нашел символически S непрактично, потому что не все пакеты предназначены для использования в качестве зависимостей в других проектах, например, пакеты Django. И я предпочитаю, чтобы они были протестированы немедленно как отдельная кодовая база. Что подводит нас к сути проблемы.

Тестирование пакетов

При использовании макетов пространства имен, то есть пакет находится в корневом каталоге проекта, где setup.py расположен, Python косвенно включает текущий каталог в sys.path Анкет Это означает, что когда вы запустите свой тестовый набор, тесты будут выполнены против кода, который у вас есть в вашем текущем рабочем каталоге, Не установленное распределение Анкет

Если вы не думаете, что это имеет большое значение, позвольте мне привести вам пример. Допустим, у вас есть библиотека с тестовым набором, которая выполняется в среде CI (непрерывная интеграция). Кто -то вводит изменение в конфигурацию библиотеки (например, setup.py ) или забывает включить несколько статических файлов в Manifest.in Файл (они не поднимаются по умолчанию). Все тесты проходят, и вы создаете новый релиз.

Релиз успешно развернут в PYPI и установлен вашим пользователями, которые начинают получать Импортеррор s. Библиотека четко установлена, но ее пустая. У него есть свои метаданные, так что все выглядит нормально от пип Точка зрения, Но код отсутствует (или его части).

Как можно избежать этого сценария? Поместив свой код в SRC/ каталог и настройка Setuptools (или какую бы систему сборки вы использовали) для поиска пакетов в SRC/ каталог. Это заставляет вас установить распределение, которое будет отправлено вашим пользователям, и запустить тестовый набор против него. Таким образом, если есть какие -либо ошибки конфигурации, вы немедленно поймаете их.

Возможно, вы также заметили, что в SRC/ макет изображено выше, Тесты каталог расположен на том же уровне, что и SRC/ каталог. pytest Документация имеет главу о Хорошая практика интеграции Что я рекомендую вам прочитать. Подход, описанный выше, соответствует этой практике именно по этим причинам, чтобы повысить надежность всего процесса разработки библиотеки.

Если вы заинтересованы в более подробной информации, я настоятельно рекомендую следующие сообщения в блоге:

Декларативная конфигурация

Чтобы сделать пакет пригодным для использования, вы должны настроить его, прежде чем развернуть его. Эта конфигурация включает в себя метаданные пакета, список зависимостей, которые необходимо установить, что нужно включить в распределение, систему сборки и т. Д. К сожалению, в этот момент есть ряд файлов, которые вы должны настроить для достижения этого.

Давайте начнем с фазы сборки. PEP-518 представил pyproject.toml который позволяет пользователям использовать любой Setuptools , пролечить или Поэзия Чтобы построить распределение из источника.

Почему это важно? Короче говоря, Когда Pip Устанавливает пакет из sdist (Распределение источника) , он выполняет setup.py Файл для создания Колесо (бинарное распределение). При выполнении setup.py , он предполагает, что его единственными зависимостями являются Setuptools и Колесо , и это нужно Setuptools сделать это. Что если это развернуто в сдержанной среде без Setuptools установил заранее? Как указать, какой пакет загружать для установки собственного пакета? Особенно, когда вам нужно Setuptools Чтобы прочитать конфигурацию в первую очередь.

pyproject.toml решает эту проблему, позволяя вам указать зависимости от сборки, и вам нужно только пип . Вы могли бы указать зависимости сборки в setup.py До этого, но опять же, вы должны были иметь Setuptools установлен, чтобы прочитать его.

Есть также другая вещь, которая проблематична с setup.py Анкет Вы могли бы найти всевозможные «вещи» в них, некоторые даже нуждались в зависимости, которые еще не были установлены. Например, setup.py Импортировал версию библиотеки из myProject/__init__.py , который также содержал импорт в зависимости. Но как мы пришли к этому? Я полагаю, разработчики пакетов рассматривали пакеты как обычные проекты и продолжали использовать Требования.txt Файлы, пользовательские сценарии сборки и различные другие процедуры, чтобы «заставить его работать».

Декларативная конфигурация это способ ограничить объем злоупотреблений. Объявив все в setup.cfg , или один день pyproject.toml Если это поддерживает это, не так много способов «взломать» ваш путь вокруг него. Я надеюсь.

Хотя я предпочитаю setup.cfg , это не значит, что вы не можете поместить все это в setup.py Чтобы достичь того же результата. Это вопрос предпочтения, хотя Подробнее и Подробнее Инструменты начали добавлять поддержку для чтения их конфигурации из pyproject.toml Анкет По моему мнению, один файл в идеале сохранит конфигурацию всего проекта, но опять же, это вопрос предпочтения.

Зависимости

Библиотеки объявляют, или должен объявить, что их зависимости в промежутке для поддержки нескольких версий одновременно, в отличие от таких проектов, как веб -приложения, где вы хотели бы указать точную версию, которая развертывается. Кроме того, вы также захотите перечислить свои дополнительные зависимости, которые пользователи могут или не могут установить, в зависимости от их потребностей. Вы также можете использовать те же дополнительные зависимости для настройки среды разработки и тестирования:

install_requires =
    Fiona>=1.7.0
    Shapely>=1.5.13
    numpy>=1.10.4
    scipy>=0.16.1
    Click>=7.0

[options.extras_require]
dev =
    tox
gdal =
    GDAL>=2.3.3
lint =
    flake8
    isort
    black
test =
    pytest>=4.0.0
    pytest-cov
    pytest-sugar
    pytest-runner
docs =
    sphinx

Разработка на основе багажника

Как только конфигурация библиотеки будет на месте, другие разработчики, скорее всего, присоединятся к структуре и развертыванию пакета, если он работает. Но сотрудничество на пакете не только запускает тестовый набор -> Обзор кода -> Merge Change. Пакеты часто обеспечивают функциональность, которая основана на ее зависимости.

Как и во всех зависимостях, существуют периоды снижения, а иногда, просто невозможно продолжать поддерживать все версии. Миграция Python от 2 до 3 является одним из таких примеров, где пакеты одновременно поддерживали обе версии Python, а затем отбросили Python 2. Эти типы изменений больше всего влияют на их пользователей, поэтому они должны выполняться с осторожностью.

Сложная часть – это поддерживает множество несовместимых версий одновременно. A compat.py Модуль, или модуль, где скрыты все края совместимости, могут только довести вас. В какой -то момент вы захотите создать релиз, который будет продолжать получать исправления безопасности, в то время как большая часть разработки и инноваций продолжается.

Именно здесь начинается управление выпуском с точки зрения системы управления версиями. Есть несколько доступных вариантов, таких как Git поток или Разработка на основе багажника (TBD). Я использовал их оба при работе над библиотеками и могу с уверенностью сказать, что TBD дает более удовлетворительные результаты.

Короче говоря, TBD требует, чтобы разработчики создавали недолговечные ветви из Мастер ветвь, которая будет объединена обратно в Мастер ответвляться. Время от времени выпускной ветвь создается из Мастер филиал, который несет обозначение версии, например release_1_11 Анкет Эта ветвь является источником для создания выпусков 1.11.x до тех пор, пока версия или ветвь не будут устарели. Между тем, все исправления безопасности, которые объединены в Мастер ветвь вишневый пик ed в Выпуск ответвляться. Если вам повезло, и разработчики, работающие над проектом, делают разумные коммиты и сообщения , это еще проще в управлении релизами, особенно в отношении установок для ошибок и исправлений безопасности.

Этот подход позволяет продолжить разработку функций в соответствии с дорожной картой проекта, не слишком беспокоясь о обратной совместимости. В конце концов, это то, что Выпуск Ветви для.

Управление изменением и версией

Одной из причин, по которой TBD был принят в первую очередь, был Changelog и управление версиями. Моя команда унаследовала индивидуальный рабочий процесс Gitflow, который ввел больше разочарования, когда кто-то представил нездоровый метод для одновременного обработки нескольких выпусков. Было практически две кодовые базы, функциональность которых была более или менее одинаковой, кроме кода, который обрабатывал проблемы совместимости между двумя версиями определенной зависимости.

Это вызвало еще больше разочарования, когда пришлось сделать новый релиз. Были выданы различные запросы на слияние, выполнены медленные трубопроводы, разрешены конфликты слияния (в основном вокруг изменений) и так далее. Там должен был быть лучший способ.

После некоторого исследования я наткнулся на TBD И все просто щелкнуло, как описано в предыдущей главе. Кроме того, я сбросил сценарий настраиваемого измененного и версии в пользу Towncrier и BumpVersion . Я не думаю, что необходимо вдаваться в слишком много деталей, так как их документации являются Preety простыми. После некоторых незначительных проблем , эти две библиотеки были успешно интегрированы в Токс рабочий процесс.

Выпуск автоматизации

Последним шагом для настройки был процесс выпуска. Это также Токс окружающая среда, названная Выпуск Это построило изменение изменений, используя Towncrier , вытащил версию пакета, используя Bumpversion , пометил его и подтолкнул изменения в источник .

Оттуда CI еще раз запустит тестовый набор, снова используя Токс Таким образом, разработчики могут легко воспроизводить проблемы, если они возникают, создайте стандартные ( sdist ) и двоичные ( wheel ) и загрузить их в PYPI, используя шпагат . Если вы используете Travis CI, вы можете использовать его собственный механизм для загрузки распределений Анкет

Вывод

Как упоминалось ранее, это один подход, который может или не может соответствовать вам и вашей команде. Каждая библиотека, используемая здесь, имеет альтернативу, и она также сводится к предпочтению.

Если вы начинаете или вам нужно создать новую библиотеку, я бы посоветовал вам использовать одну FO FO FOHON CookieCutters, такие как CookieCutter-Pybibrary Анкет Вы также можете построить свой собственный, как и я. Beats Copy/Daking Coded из существующего проекта или документации.

Оригинал: “https://dev.to/fitodic/python-package-distribution-can-be-easy-4f3f”