Как создать пакет в python
Перейти к содержимому

Как создать пакет в python

  • автор:

Учимся создавать пакеты Python

imageПочему важно уметь создавать пакеты Python?
• Пакеты легко устанавливаются (pip install demo).
• Пакеты упрощают разработку (Команда pip install -e устанавливает ваш пакет и следит за тем, чтобы он сам обновлялся в ходе всего процесса разработки).
• Пакеты легко запускать и тестировать (from demo.main import say_hello, а затем тестируем функцию).
• Пакеты легко версионировать, при этом вы не рискуете нарушить работу кода, зависящего от этого пакета (pip install demo==1.0.3).

В чем отличия между библиотекой, пакетом и модулем:
• Модуль: это .py-файл, в котором содержатся функции, образующие некоторое единство
• Пакет: это коллекция модулей, которую можно распространять
• Библиотека: это пакет, не учитывающий контекста
image
Заключать код Python в пакеты достаточно просто. Для этого вам понадобится всего один скрипт setup.py, позволяющий упаковать код сразу в нескольких форматах для распространения.

1. Подготовка к упаковке

Давайте воспользуемся такой структурой каталогов, которая описана в этом посте, и создадим здесь виртуальное окружение:

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

Теперь можно вызвать этот скрипт, который позволяет упаковать ваш код несколькими способами:

Давайте запустим первый вариант из списка. Если все пройдет успешно, то вы сможете импортировать ваш код следующим образом:

Теперь, когда мы в состоянии установить проект, давайте внимательнее рассмотрим аргументы, передаваемые функции setuptools.setup:
1. name: имя вашей функции
2. version: результатом каждого изменения, вносимого в код, должна быть новая версия пакета; в противном случае возможна ситуация, в которой разработчики устанавливают прежнюю версию пакета, которая вдруг станет функционировать не так как раньше и сломает код.
3. packages: список путей ко всем вашим файлам python
4. install_requires: список имен и версий пакетов (точно как в файле requirements.txt)
Как видите, я написал простую функцию read_pipenv_dependencies для считывания из Pipfile.lock зависимостей, не попадающих в разработку (non-dev). В данном случае я не хочу задавать зависимости вручную. Также я воспользуюсь os.getenv для считывания переменной окружения и определения версии пакета – пожалуй, это хорошие сюжеты для новых постов.

2. Документация

Точно как при считывании Pipfile.lock для указания зависимостей, я могу прочитать и файл README.md, чтобы отобразить полезную документацию как long_description. Подробнее о том, как это делается, рассказано в packaging.python.org.

Кроме того, можно создать полноценную веб-страницу с документацией при помощи readthedocs и sphinx. Создаем каталог для вашей документации:

Командой quickstart генерируем каталог с исходниками для вашей документации:

Теперь можно приступать к наполнению файла docs/index.rst самой документацией. Подробнее о том, как автоматизировать этот процесс, рассказано на сайте sphinx-doc.org.

3. Линтинг и тестирование

В рамках процесса упаковки целесообразно применить статический анализ кода, линтинг и тестирование.

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

4. Makefile

По мере того, как мы быстро вводим все новые команды, нужные для упаковки нашего конкретного проекта, распространенные команды полезно записывать. В большинстве инструментов для автоматизации сборки (например, в Gradle или npm) эта возможность предоставляется по умолчанию.

Make – это инструмент, организующий компиляцию кода. Традиционно используется в c-ориентированных проектах. Но с его помощью можно выполнять и любые другие команды.
По умолчанию при использовании make выполняется первая команда из списка. Таким образом, в следующем примере будет выполнена make help, а на экран будет выведено содержимое Makefile.

Если сделать make test, то сначала будет выполнена make dev, поскольку в файле Makefile она указана как зависимость:

Теперь, как видите, новым разработчикам достаточно легко внести свой вклад в проект. Распространенные команды у них как на ладони и, например, сразу видно, как собрать колесо: make build.

5. Установка колеса

Если запустить make build, программа использует файл setup.py, чтобы создать дистрибутив колеса. Файл .whl находится в каталоге dist/, в имени файла должно присутствовать 0.0.dev0. Теперь можно указать переменную окружения, чтобы изменить версию колеса:

Имея колесо, можно создать где-нибудь на ПК новый каталог, скопировать в него колесо, а затем установить его при помощи:

Вывод списка установленных файлов:

6. Включить конфигурационные файлы

Добавить данные в пакет можно и другим способом, включив в скрипт setup.py следующие строки:

После этого можно будет прочитать файл при помощи следующей функции:

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

7. DevOps

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

Здесь рассмотрим для примера Azure DevOps, где на git tags, а также в ветке master будет инициироваться процесс, представленный ниже.

Посмотрите код, и ниже мы обсудим его различные стадии и задачи:

На этапе Test мы устанавливаем проект в контейнер конвейера, не создавая виртуального окружения. Затем выполняем команды make lint и make test, точно как вы сделали бы это на вашей машине.

На этапе Build попытаемся извлечь версию пакета, ориентируясь на тег git, а еще соберем резервную версию пакета. Выполним команду python setup.py bdist_wheel для сборки колеса, учитывая, что у нас уже установлена переменная окружения, соответствующая версии пакета. Наконец, мы публикуем артефакт в числе других артефактов Azure DevOps и (по желанию) можем выложить в ленту.

Чтобы опубликовать пакет в ленте, вам потребуется файл .pypirc, а затем вы можете скопировать содержимое ленты, созданной в Azure DevOps. Выглядеть файл будет примерно так:

О том, как устанавливать пакеты из частной ленты, рассказано здесь.

Пакеты Python — создание и доступ

Пакеты Python помогают нам управлять модулями и скриптами Python. Это обычные каталоги со сценарием инициализации — __init__.py.

Как создать пакет Python?

Мы можем создать пакет, выполнив следующие шаги.

  1. Создайте каталог пакета – для этого мы можем использовать terminal или Python IDE.
  2. Создать __init__.py файл — это необходимо для преобразования обычного каталога в пакет python. Этот файл используется для инициализации пакета и перечисления всех модулей. В самом простом виде этот файл может быть пустым.

Что мы можем сохранить в пакете?

  • Файл инициализации;
  • Модули;
  • Скрипты;
  • Любой другой тип файлов.

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

Можно ли создавать подпакеты?

Да, мы можем создать пакет внутри другого пакета. Мы также должны следовать правилам упаковки, чтобы создать подпакет.

Примеры

Давайте рассмотрим несколько примеров создания и использования пакетов.

1. Создание пакета

Python пакеты

2. Добавление модулей

Допустим, у нас есть два модуля Python — math.py и str_utils.py. У них есть несколько функций, которые будут использоваться в нашей программе.

Мы хотим добавить эти модули в наши пакеты. Просто скопируйте эти файлы в каталог пакетов, где вы хотите сохранить эти модули.

добавление модуля в пакет

3. Импорт пакета

Синтаксис для импорта модуля Python внутри пакета:

Python использует переменную sys.path для поиска пакетов и модулей. Текущий каталог является частью переменной sys.path . Поэтому мы будем хранить наш скрипт python в каталоге python-packages. В противном случае нам придется добавить местоположение пакета в переменную sys.path .

Вот код my_script.py для доступа к модулям из пакетов и вызова их функций.

Модуль Импорта

Мы также можем импортировать модуль, используя синтаксис ниже:

Вот обновленный пример доступа к модулям «math» и «str_utils» в нашей программе.

Из Модуля Импорта Пакетов

4. Импорт * из пакета

Мы можем импортировать каждый модуль из пакета, используя следующий синтаксис.

В этом случае Python ищет в sub_package2 пакеты, модули и функции. Это может вызвать побочные эффекты из-за импорта того, чего вы не хотите. Кроме того, это очень долгий процесс.

Мы можем определить список импортируемых модулей, создав переменную __all__ в файле __init__.py.

утилиты / __ init__.py:

утилиты / строки / __ init__.py:

Обновленный код my_script.py:

Файл Инициализации Всех Модулей

Обратите внимание, что код python в __init__.py выполняется первым, когда пакеты инициализируются и импортируются.

Как добавить пакет в системный путь

Невозможно всегда зависеть от иерархии каталогов для импорта модулей пакета. Мы можем добавить наш собственный пакет в переменную sys.path, а затем импортировать их в любой скрипт.

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

Packaging Python Projects¶

This tutorial walks you through how to package a simple Python project. It will show you how to add the necessary files and structure to create the package, how to build the package, and how to upload it to the Python Package Index (PyPI).

If you have trouble running the commands in this tutorial, please copy the command and its output, then open an issue on the packaging-problems repository on GitHub. We’ll do our best to help you!

Some of the commands require a newer version of pip , so start by making sure you have the latest version installed:

A simple project¶

This tutorial uses a simple project named example_package_YOUR_USERNAME_HERE . If your username is me , then the package would be example_package_me ; this ensures that you have a unique package name that doesn’t conflict with packages uploaded by other people following this tutorial. We recommend following this tutorial as-is using this project, before packaging your own project.

Create the following file structure locally:

The directory containing the Python files should match the project name. This simplifies the configuration and is more obvious to users who install the package.

__init__.py is required to import the directory as a package, and should be empty.

example.py is an example of a module within the package that could contain the logic (functions, classes, constants, etc.) of your package. Open that file and enter the following content:

If you are unfamiliar with Python’s modules and import packages , take a few minutes to read over the Python documentation for packages and modules.

Once you create this structure, you’ll want to run all of the commands in this tutorial within the packaging_tutorial directory.

Creating the package files¶

You will now add files that are used to prepare the project for distribution. When you’re done, the project structure will look like this:

Creating a test directory¶

tests/ is a placeholder for test files. Leave it empty for now.

Creating pyproject.toml¶

pyproject.toml tells “frontend” build tools like pip and build what “backend” tool to use to create distribution packages for your project. You can choose from a number of backends; this tutorial uses Hatchling by default, but it will work identically with setuptools , Flit , PDM , and others that support the [project] table for metadata .

Some build backends are part of larger tools that provide a command-line interface with additional features like project initialization and version management, as well as building, uploading, and installing packages. This tutorial uses single-purpose tools that work independently.

Open pyproject.toml and enter one of these [build-system] tables:

requires is a list of packages that are needed to build your package. You don’t need to install them; build frontends like pip will install them automatically in a temporary, isolated virtual environment for use during the build process.

build-backend is the name of the Python object that frontends will use to perform the build.

Configuring metadata¶

Open pyproject.toml and enter the following content. Change the name to include your username; this ensures that you have a unique package name that doesn’t conflict with packages uploaded by other people following this tutorial.

name is the distribution name of your package. This can be any name as long as it only contains letters, numbers, . , _ , and — . It also must not already be taken on PyPI. Be sure to update this with your username for this tutorial, as this ensures you won’t try to upload a package with the same name as one which already exists.

version is the package version. See the version specifier specification for more details on versions. Some build backends allow it to be specified another way, such as from a file or a git tag.

authors is used to identify the author of the package; you specify a name and an email for each author. You can also list maintainers in the same format.

description is a short, one-sentence summary of the package.

readme is a path to a file containing a detailed description of the package. This is shown on the package detail page on PyPI. In this case, the description is loaded from README.md (which is a common pattern). There also is a more advanced table form described in the project metadata specification .

requires-python gives the versions of Python supported by your project. Installers like pip will look back through older versions of packages until it finds one that has a matching Python version.

classifiers gives the index and pip some additional metadata about your package. In this case, the package is only compatible with Python 3, is licensed under the MIT license, and is OS-independent. You should always include at least which version(s) of Python your package works on, which license your package is available under, and which operating systems your package will work on. For a complete list of classifiers, see https://pypi.org/classifiers/.

urls lets you list any number of extra links to show on PyPI. Generally this could be to the source, documentation, issue trackers, etc.

See the project metadata specification for details on these and other fields that can be defined in the [project] table. Other common fields are keywords to improve discoverability and the dependencies that are required to install your package.

Creating README.md¶

Open README.md and enter the following content. You can customize this if you’d like.

Creating a LICENSE¶

It’s important for every package uploaded to the Python Package Index to include a license. This tells users who install your package the terms under which they can use your package. For help picking a license, see https://choosealicense.com/. Once you have chosen a license, open LICENSE and enter the license text. For example, if you had chosen the MIT license:

Most build backends automatically include license files in packages. See your backend’s documentation for more details.

Including other files¶

The files listed above will be included automatically in your source distribution . If you want to include additional files, see the documentation for your build backend.

Generating distribution archives¶

The next step is to generate distribution packages for the package. These are archives that are uploaded to the Python Package Index and can be installed by pip .

Создание python-пакетов (aka setup scripts)

Одна из действительно полезных вещей в 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:

Открыв браузер по адресу http://127.0.0.1:5000 вы должны увидеть нашу страницу.

Управление файлами проекта (MANIFEST.in)

На текущий момент при сборке нашего пакета distutils включает в него только python-файлы. Необходимо включить в него файл helloworld/templates/index.html без которого проект работать не будет.

Чтобы сделать это мы должны сообщить distutils какие еще файлы надо включать в наш проект. Один из способов — это создание файла MANIFEST.in :

Данная команда указывает distutils на включение в проект всех html файлов в директории helloworld/templates .

Также придется обновить setup.py :

Теперь шаблоны будут включены в наш проект.

Создание и запуск тестов

Хорошей практикой считается создание тестов для вашего проекта. Добавим простейшую реализацию, файл tests.py :

И обновим setup.py :

Теперь мы можем произвести предварительное тестирование нашего проекта:

Обратите внимание, что для запуска тестов даже не нужно создание виртуального окружения. Необходимые зависимости будут скачаны в директорию проекта в виде egg пакетов.

Публикация пакета на pypi.python.org

Прежде чем вы сможете опубликовать свой проект вам необходимо зарегистрироваться на PyPi. Запишите ваши реквизиты в файле

Все ваш проект готов к публикации. Достаточно ввести соответствующую команду:

Вы не сможете опубликовать пакет helloworld , тк данное имя проекта уже занято.

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *