Как написать библиотеку для python на python

Python — отличный язык программирования, но упаковка — одна из его самых слабых точек. Это общеизвестный в сообществе факт. За последние годы установка, импорт, использование и создание пакетов значительно улучшилась, но она все еще не соответствует новым языкам, таким как Go и Rust, которые многому научились в борьбе с Python и другими зрелыми языками.

В этом уроке вы узнаете все, что вам нужно знать о написании, упаковке и распространении собственных пакетов.

Как написать библиотеку Python

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

Давайте быстро напишем небольшой пакет Python 3 и проиллюстрируем все эти понятия.

Пакет Pathology

Python 3 имеет отличный объект Path, который является большим улучшением по сравнению с неудобным модулем Os.path Python 2. Но ему не хватает одной важной возможности — найти путь к текущему сценарию. Это очень важно, если вы хотите найти файлы доступа относительно текущего скрипта.

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

Вот как вы это делаете в Python:

1
import pathlib
2

3
script_dir = pathlib.Path(__file__).parent.resolve()

Чтобы получить доступ к файлу с именем ‘file.txt’ в подкаталоге данных в каталоге текущего скрипта, вы можете использовать следующий код:print(open(str(script_dir/'data/file.txt').read())

С пакетом pathology у вас есть встроенный метод script_dir, и вы используете его следующим образом:

1
from pathology.Path import script_dir
2

3
print(open(str(script_dir()/'data/file.txt').read())
4

Да, это глоток свежего воздуха. Пакет патологии очень прост. Он выводит свой собственный класс Path из Pathlib Path и добавляет статический script_dir(), который всегда возвращает путь вызывающего скрипта.

Вот реализация:

1
import pathlib
2
import inspect
3

4
class Path(type(pathlib.Path())):
5
    @staticmethod
6
    def script_dir():
7
        print(inspect.stack()[1].filename)
8
        p = pathlib.Path(inspect.stack()[1].filename)
9
        return p.parent.resolve()

Из-за кросс-платформенной реализации pathlib.Path вы можете получить непосредственно от него и должны быть получены из определенного подкласса (PosixPath или WindowsPath). Разрешение dir-файла сценария использует модуль проверки, чтобы найти вызывающего, а затем его атрибут имени файла.

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

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

1
import os
2
import shutil 
3
from unittest import TestCase
4
from pathology.path import Path
5

6

7
class PathTest(TestCase):
8
    def test_script_dir(self):
9
        expected = os.path.abspath(os.path.dirname(__file__))
10
        actual = str(Path.script_dir())
11
        self.assertEqual(expected, actual)
12

13
    def test_file_access(self):
14
        script_dir = os.path.abspath(os.path.dirname(__file__))
15
        subdir = os.path.join(script_dir, 'test_data')
16
        if Path(subdir).is_dir():
17
            shutil.rmtree(subdir)
18
        os.makedirs(subdir)
19
        file_path = str(Path(subdir)/'file.txt')
20
        content = '123'
21
        open(file_path, 'w').write(content)
22
        test_path = Path.script_dir()/subdir/'file.txt'
23
        actual = open(str(test_path)).read()
24

25
        self.assertEqual(content, actual)

Путь Python

Пакеты Python должны быть установлены где-то на пути поиска Python, который должен быть импортирован модулями Python. Путь поиска Python представляет собой список каталогов и всегда доступен в sys.path. Вот мой текущий sys.path:

1
>>> print('n'.join(sys.path))
2

3
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python36.zip
4
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6
5
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/lib-dynload
6
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages
7
/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg 

Обратите внимание, что первая пустая строка вывода представляет текущий каталог, поэтому вы можете импортировать модули из текущего рабочего каталога, что бы это ни было. Вы можете напрямую добавлять или удалять каталоги в / из sys.path.

Вы также можете определить переменную среды PYTHONPATH, и есть несколько других способов ее контролировать. Стандартные site-packages включены по умолчанию, и именно там устанавливаются пакеты, которые вы устанавливаете с помощью pip.

Как упаковать библиотеку Python

Теперь, когда у нас есть наш код и тесты, давайте упакуем все это в нужную библиотеку. Python обеспечивает простой способ через модуль настройки. Вы создаете файл setup.py в корневом каталоге вашего пакета. Затем, чтобы создать исходный дистрибутив, вы запустите: python setup.py sdist

Чтобы создать двоичный дистрибутив, называемый колесом, вы запускаете: python setup.py bdist_wheel

Вот файл setup.py пакета патологии:

1
from setuptools import setup, find_packages
2

3
setup(name='pathology',
4
      version='0.1',
5
      url='https://github.com/the-gigi/pathology',
6
      license='MIT',
7
      author='Gigi Sayfan',
8
      author_email='the.gigi@gmail.com',
9
      description='Add static script_dir() method to Path',
10
      packages=find_packages(exclude=['tests']),
11
      long_description=open('README.md').read(),
12
      zip_safe=False)

Он включает в себя множество метаданных в дополнение к элементу ‘packages’, который использует функцию find_packages(), импортированную из setuptools, чтобы найти подпакеты.

Давайте построим дистрибутив источника:

1
$ python setup.py sdist
2
running sdist
3
running egg_info
4
creating pathology.egg-info
5
writing pathology.egg-info/PKG-INFO
6
writing dependency_links to pathology.egg-info/dependency_links.txt
7
writing top-level names to pathology.egg-info/top_level.txt
8
writing manifest file 'pathology.egg-info/SOURCES.txt'
9
reading manifest file 'pathology.egg-info/SOURCES.txt'
10
writing manifest file 'pathology.egg-info/SOURCES.txt'
11
warning: sdist: standard file not found: should have one of README, README.rst, README.txt
12

13
running check
14
creating pathology-0.1
15
creating pathology-0.1/pathology
16
creating pathology-0.1/pathology.egg-info
17
copying files to pathology-0.1...
18
copying setup.py -> pathology-0.1
19
copying pathology/__init__.py -> pathology-0.1/pathology
20
copying pathology/path.py -> pathology-0.1/pathology
21
copying pathology.egg-info/PKG-INFO -> pathology-0.1/pathology.egg-info
22
copying pathology.egg-info/SOURCES.txt -> pathology-0.1/pathology.egg-info
23
copying pathology.egg-info/dependency_links.txt -> pathology-0.1/pathology.egg-info
24
copying pathology.egg-info/not-zip-safe -> pathology-0.1/pathology.egg-info
25
copying pathology.egg-info/top_level.txt -> pathology-0.1/pathology.egg-info
26
Writing pathology-0.1/setup.cfg
27
creating dist
28
Creating tar archive
29
removing 'pathology-0.1' (and everything under it)

Предупреждение связано с тем, что я использовал нестандартный файл README.md. Это безопасно поэтому игнорируем. Результатом является файл tar-gzipped в каталоге dist:

1
$ ls -la dist
2
total 8
3
drwxr-xr-x   3 gigi.sayfan  gigi.sayfan   102 Apr 18 21:20 .
4
drwxr-xr-x  12 gigi.sayfan  gigi.sayfan   408 Apr 18 21:20 ..
5
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  1223 Apr 18 21:20 pathology-0.1.tar.gz

И вот двоичное распределение:

1
$ python setup.py bdist_wheel
2
running bdist_wheel
3
running build
4
running build_py
5
creating build
6
creating build/lib
7
creating build/lib/pathology
8
copying pathology/__init__.py -> build/lib/pathology
9
copying pathology/path.py -> build/lib/pathology
10
installing to build/bdist.macosx-10.7-x86_64/wheel
11
running install
12
running install_lib
13
creating build/bdist.macosx-10.7-x86_64
14
creating build/bdist.macosx-10.7-x86_64/wheel
15
creating build/bdist.macosx-10.7-x86_64/wheel/pathology
16
copying build/lib/pathology/__init__.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology
17
copying build/lib/pathology/path.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology
18
running install_egg_info
19
running egg_info
20
writing pathology.egg-info/PKG-INFO
21
writing dependency_links to pathology.egg-info/dependency_links.txt
22
writing top-level names to pathology.egg-info/top_level.txt
23
reading manifest file 'pathology.egg-info/SOURCES.txt'
24
writing manifest file 'pathology.egg-info/SOURCES.txt'
25
Copying pathology.egg-info to build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1-py3.6.egg-info
26
running install_scripts
27
creating build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1.dist-info/WHEEL

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

1
$ ls -la dist
2
total 16
3
drwxr-xr-x   4 gigi.sayfan  gigi.sayfan   136 Apr 18 21:24 .
4
drwxr-xr-x  13 gigi.sayfan  gigi.sayfan   442 Apr 18 21:24 ..
5
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  2695 Apr 18 21:24 pathology-0.1-py3-none-any.whl
6
-rw-r--r--   1 gigi.sayfan  gigi.sayfan  1223 Apr 18 21:20 pathology-0.1.tar.gz

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

Как раздавать пакет Python

Python имеет центральный репозиторий пакетов, называемый PyPI (индекс пакетов Python). Когда вы устанавливаете пакет Python с помощью pip, он загружает пакет из PyPI (если вы не укажете другой репозиторий). Чтобы распространять наш пакет патологии, нам нужно загрузить его в PyPI и предоставить некоторые дополнительные метаданные, которые требуется PyPI. Шаги:

  • Создайте учетную запись на PyPI (только один раз).
  • Зарегистрируйте свой пакет.
  • Загрузите свой пакет.

Создайте аккаунт

Вы можете создать учетную запись на веб-сайте PyPI. Затем создайте файл .pypirc в своем домашнем каталоге:

1
[distutils] 
2
index-servers=pypi
3
 
4
[pypi]
5
repository = https://pypi.python.org/pypi
6
username = the_gigi

В целях тестирования вы можете добавить «pypitest» индексный сервер в ваш .pypirc файл:

1
[distutils]
2
index-servers=
3
    pypi
4
    pypitest
5

6
[pypitest]
7
repository = https://testpypi.python.org/pypi
8
username = the_gigi
9

10
[pypi]
11
repository = https://pypi.python.org/pypi
12
username = the_gigi

Зарегистрируйте свой пакет

Если это первый выпуск вашего пакета, вам необходимо зарегистрировать его с помощью PyPI. Используйте команду register setup.py. Она попросит вас ввести пароль. Обратите внимание, что я указываю его на тестовый репозиторий:

1
$ python setup.py register -r pypitest
2
running register
3
running egg_info
4
writing pathology.egg-info/PKG-INFO
5
writing dependency_links to pathology.egg-info/dependency_links.txt
6
writing top-level names to pathology.egg-info/top_level.txt
7
reading manifest file 'pathology.egg-info/SOURCES.txt'
8
writing manifest file 'pathology.egg-info/SOURCES.txt'
9
running check
10
Password:
11
Registering pathology to https://testpypi.python.org/pypi
12
Server response (200): OK

Загрузите свой пакет

Теперь, когда пакет зарегистрирован, мы можем его загрузить. Я рекомендую использовать twine, который более безопасен. Установите его, как обычно, с помощью pip install twine. Затем загрузите свой пакет с помощью twine и укажите свой пароль (отредактированный ниже):

1
$ twine upload -r pypitest -p <redacted> dist/*
2
Uploading distributions to https://testpypi.python.org/pypi
3
Uploading pathology-0.1-py3-none-any.whl
4
[================================] 5679/5679 - 00:00:02
5
Uploading pathology-0.1.tar.gz
6
[================================] 4185/4185 - 00:00:01 

Для более глубокого погружения в тему распространения ваших пакетов ознакомьтесь с разделом «Пакеты Python».

Заключение

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

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

Время на прочтение
10 мин

Количество просмотров 22K

Каждый разработчик ПО должен знать как создать библиотеку с нуля. В процессе работы Вы можете многому научиться. Только не забудьте запастись временем и терпением.

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

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

Шаг 1: Составьте план

Мы планируем создать простую библиотеку для использования в Python. Данная библиотека позволит пользователю легко конвертировать блокнот Jupyter в HTML-файл или Python-скрипт.
Первая итерация нашей библиотеки позволит вызвать функцию, которая выведет определенное сообщение.

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

Шаг 2: Дайте имя библиотеке

Придумывать имена сложно. Они должны быть короткими, уникальными и запоминающимися. Также они должны быть написаны строчными буквами, без прочерков и прочих знаков препинания. Подчеркивание не рекомендуется. В процессе создания библиотеки убедитесь, что придуманное Вами имя доступно на GitHub, Google и PyPi.

Если Вы надеетесь и верите, что однажды Ваша библиотека получит 10000 звезд GitHub, то стоит проверить, доступно ли данное имя в социальных сетях. В данном примере я назову свою библиотеку notebookc, потому что это имя доступное, короткое и более-менее описывает суть моей задумки.

Шаг 3. Настройте среду

Убедитесь, что у вас установлены и настроены Python 3.7, GitHub и Homebrew. Если вам нужно что-то из этого, вот подробности:

Python

Скачайте Python 3.7 здесь и установите его.

GitHub

Если у вас нет учетной записи GitHub, перейдите по этой ссылке и оформите бесплатную подписку. Посмотрите, как установить и настроить Git здесь. Вам потребуется утилита командной строки. Перейдите по ссылкам, скачайте и установите все, что Вам понадобится, придумайте юзернейм и укажите электронную почту.

Homebrew

Homebrew — менеджер библиотек для Mac. Инструкции по установке найдете здесь.

Venv

Начиная с 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 вашим именем. Активируйте среду таким образом:

source my_env/bin/activate

Теперь вы должны наблюдать (my_env) (или имя, которое вы выбрали для вашей виртуальной среды) в крайнем левом углу терминала.

Когда закончите работу, деактивируйте виртуальную среду с помощью deactivate.

Теперь давайте настроим GitHub.

Шаг 4: Создайте организацию в GitHub

GitHub — лидер на рынке реестров контроля версий. Еще две популярные опции — GitLab и Bitbucket. В данном гиде мы будем использовать именно GitHub.

Вам придется часто обращаться к Git и GitHub, поэтому если Вы не знакомы с системой, то можете обратиться к моей статье.

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

image

Шаг 5: Настройте GitHub Repo

Создайте новый репозиторий. Я назвал свой notebookc.

image

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

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

Для этого проекта я выбрал третью версию Открытого лицензионного соглашения GNU, потому что она популярная, проверенная и “гарантирует пользователям свободу использования, изучения, обмена и изменения программного обеспечения” — источник.

image

Шаг 6: Клонируйте и добавьте директории

Выберите, куда Вы хотите клонировать Ваш репозиторий или выполните следующую функцию:

git clone https://github.com/notebooktoall/notebookc.git

Подставьте свою организацию и репозиторий.

Перейдите в папку проекта с помощью десктопного графического интерфейса или редактора кода. Или используйте командную строку с 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.

pip==19.0.3
wheel==0.33.1

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

Закрепите версии вашей библиотеку в 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):

def convert(my_name):
    """
    Print a line about converting a notebook.
    Args:
        my_name (str): person's name
    Returns:
        None
    """

    print(f"I'll convert a notebook for you some day, {my_name}.")

Вот наша функция во всей красе.

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

Шаг 9: Создайте setup.py

Файл setup.py — это скрипт сборки для вашей библиотеки. Функция setup из Setuptools создаст библиотеку для загрузки в PyPI. Setuptools содержит информацию о вашей библиотеке, номере версии и о том, какие другие библиотеки требуются для пользователей.

Вот мой пример файла setup.py:

from setuptools import setup, find_packages

with open("README.md", "r") as readme_file:
    readme = readme_file.read()

requirements = ["ipython>=6", "nbformat>=4", "nbconvert>=5", "requests>=2"]

setup(
    name="notebookc",
    version="0.0.1",
    author="Jeff Hale",
    author_email="jeffmshale@gmail.com",
    description="A package to convert your Jupyter Notebook",
    long_description=readme,
    long_description_content_type="text/markdown",
    url="https://github.com/your_package/homepage/",
    packages=find_packages(),
    install_requires=requirements,
    classifiers=[
        "Programming Language :: Python :: 3.7",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
    ],
)

Обратите внимание, что 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==1.13.0

Затем закрепите Twine в Вашей виртуальной среде, переустановив библиотеки needs_dev.txt.

pip install -r requirements_dev.txt

Затем выполните следующую команду, чтобы создать файлы библиотеки:

python setup.py sdist bdist_wheel

Необходимо создать несколько скрытых папок: 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. Введите следующую команду — никаких изменений не требуется.

twine upload --repository-url https://test.pypi.org/legacy/ dist/*

Вам будет предложено ввести имя пользователя и пароль. Не забывайте, что TestPyPI и PyPI имеют разные пароли!

При необходимости исправьте все ошибки, создайте новый номер версии в файле setup.py и удалите старые артефакты сборки: папки build, dist и egg. Перестройте задачу с помощью python setup.py sdist bdist_wheel и повторно загрузите с помощью Twine. Наличие номеров версий в TestPyPI, которые ничего не значат, особой роли не играют — Вы единственный, кто будет использовать эти версии библиотек.

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

Шаг 13: Проверьте и используйте установленную библиотеку

Создайте еще одну вкладку в командном интерпретаторе и запустите другую виртуальную среду.

python3.7 -m venv my_env

Активируйте ее.

source my_env/bin/activate

Если Вы уже загрузили свою библиотеку на официальный сайт PyPI, то сможете выполнить команду pip install your-package. Мы можем извлечь библиотеку из TestPyPI и установить его с помощью измененной команды.

Вот официальные инструкции по установке вашей библиотеки из TestPyPI:

Вы можете заставить pip загружать библиотеки из TestPyPI вместо PyPI, указав это в index-url.

pip install --index-url https://test.pypi.org/simple/ my_package

Если хотите, чтобы pip также извлекал и другие библиотеки из PyPI, Вы можете добавить — extra-index-url для указания на PyPI. Это полезно, когда тестируемая библиотека имеет зависимости:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple my_package

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

Вы должны увидеть последнюю версию библиотеки, установленного в Вашей виртуальной среде.

Чтобы убедиться, что Вы можете использовать свою библиотеку, запустите сеанс IPython в терминале следующим образом:

python

Импортируйте свою функцию и вызовите ее со строковым аргументом. Вот как выглядит мой код:

from notebookc.notebookc import convert

convert(“Jeff”)

После я получаю следующий вывод:

I’ll convert a notebook for you some day, Jeff.

(Когда-нибудь я конвертирую для тебя блокнот, Джефф)

Я в Вас верю.

Шаг 14: Залейте код на PyPI

Залейте Ваш код на настоящий сайт PyPI, чтобы люди могли скачать его с помощью pip install my_package.

Загрузить код можно так:

twine upload dist/*

Обратите внимание, что Вам нужно обновить номер версии в setup.py, если Вы хотите залить новую версию в PyPI.

Отлично, теперь давайте загрузим нашу работу на GitHub.

Шаг 15: Залейте библиотеку на GitHub

Убедитесь, что Ваш код сохранен.

Моя папка проекта notebookc выглядит так:

.git
.gitignore
LICENSE
README.md
requirements_dev.txt
setup.py
notebookc/__init__.py
notebookc/notebookc.py

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

Переместите вашу локальную ветку на GitHub с помощью git push origin my_branch.

Шаг 16: Создайте и объедините PR

В браузере перейдите к GitHub. У Вас должна появиться опция сделать pull-запрос. Нажимайте на зеленые кнопки, чтобы создать, объединить PR и чтобы убрать удаленную ветку.
Вернувшись в терминал, удалите локальную ветку с git branch -d my_feature_branch.

Шаг 17: Обновите рабочую версию на GitHub

Создайте новую версию библиотеки на GitHub, кликнув на релизы на главной странице репозитория. Введите необходимую информацию о релизе и сохраните.

На сегодня достаточно!

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

Итог: 17 шагов к рабочей библиотеке

  1. Составьте план.
  2. Дайте имя библиотеке.
  3. Настройте среду.
  4. Создайте организацию в GitHub.
  5. Настройте GitHub Repo.
  6. Клонируйте и добавьте директории.
  7. Скачайте и установите requirements_dev.txt.
  8. Поработайте с кодом.
  9. Создайте setup.py.
  10. Соберите первую версию.
  11. Создайте учётную запись TestPyPI.
  12. Опубликуйте библиотеку в PyPI.
  13. Проверьте и используйте установленную библиотеку.
  14. Залейте код на PyPI.
  15. Залейте библиотеку на GitHub.
  16. Создайте и объедините PR.
  17. Обновите рабочую версию на GitHub.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:

  • Курс по Machine Learning (12 недель)
  • Курс «Профессия Data Scientist» (24 месяца)
  • Курс «Профессия Data Analyst» (18 месяцев)
  • Курс «Python для веб-разработки» (9 месяцев)

Читать еще

  • Крутые Data Scientist не тратят время на статистику
  • Как стать Data Scientist без онлайн-курсов
  • Шпаргалка по сортировке для Data Science
  • Data Science для гуманитариев: что такое «data»
  • Data Scienсe на стероидах: знакомство с Decision Intelligence

Добавлено 30 июля 2020 в 22:33

Содержание главы

Погружение

Вы хотите выпустить скрипт, библиотеку, фреймворк или приложение на Python? Превосходно. Миру нужно больше кода на Python. Python 3 поставляется с системой создания пакетов Distutils. Distutils – это много всего: инструмент сборки (для вас), инструмент установки (для ваших пользователей), формат метаданных пакета (для поисковых систем) и многое другое. Он интегрирован с каталогом пакетов Python PyPI, центральным репозиторием библиотек Python с открытым исходным кодом.

Все эти аспекты Distutils сосредоточены вокруг сценария установки, который обычно называется setup.py. На самом деле, вы уже видели в этой книге несколько скриптов установки Distutils. Вы использовали Distutils для установки httplib2 в HTTP веб-сервисах и еще раз для установки chardet в главе 15 «Учебный пример: портирование chardet на Python 3».

В данной главе вы узнаете, как работают скрипты установки для chardet и httplib2, и пройдете через процесс релиза своего собственного программного обеспечения на Python.

# setup.py модуля chardet
from distutils.core import setup
setup(
    name = "chardet",
    packages = ["chardet"],
    version = "1.0.2",
    description = "Universal encoding detector",
    author = "Mark Pilgrim",
    author_email = "mark@diveintomark.org",
    url = "http://chardet.feedparser.org/",
    download_url = "http://chardet.feedparser.org/download/python3-chardet-1.0.1.tgz",
    keywords = ["encoding", "i18n", "xml"],
    classifiers = [
        "Programming Language :: Python",
        "Programming Language :: Python :: 3",
        "Development Status :: 4 - Beta",
        "Environment :: Other Environment",
        "Intended Audience :: Developers",
        "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
        "Operating System :: OS Independent",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Text Processing :: Linguistic",
        ],
    long_description = """
Universal character encoding detector
-------------------------------------

Detects
 - ASCII, UTF-8, UTF-16 (2 variants), UTF-32 (4 variants)
 - Big5, GB2312, EUC-TW, HZ-GB-2312, ISO-2022-CN (Traditional and Simplified Chinese)
 - EUC-JP, SHIFT_JIS, ISO-2022-JP (Japanese)
 - EUC-KR, ISO-2022-KR (Korean)
 - KOI8-R, MacCyrillic, IBM855, IBM866, ISO-8859-5, windows-1251 (Cyrillic)
 - ISO-8859-2, windows-1250 (Hungarian)
 - ISO-8859-5, windows-1251 (Bulgarian)
 - windows-1252 (English)
 - ISO-8859-7, windows-1253 (Greek)
 - ISO-8859-8, windows-1255 (Visual and Logical Hebrew)
 - TIS-620 (Thai)

This version requires Python 3 or later; a Python 2 version is available separately.
"""
)

chardet и httplib2 имеют открытый исходный код, но нет требований, под какой-либо конкретной лицензией вам выпускать собственные библиотеки на Python. Процесс, описанный в данной главе, будет работать для любого программного обеспечения на Python, независимо от лицензии.

16.2 Вещи, которые Distutils не может сделать за вас

Релиз вашего первого пакета Python – сложный процесс (релиз второго немного проще). Distutils пытается максимально автоматизировать его, но есть некоторые вещи, которые вы просто должны сделать сами.

  • Выбрать лицензию. Это сложная тема, связанная с политикой и опасностями. Если вы хотите выпустить свое программное обеспечение с открытым исходным кодом, я скромно предлагаю пять советов:
    1. Не пишите свою собственную лицензию.
    2. Не пишите свою собственную лицензию.
    3. Не пишите свою собственную лицензию.
    4. Это не обязательно должен быть GPL, но она должна быть GPL-совместимой.
    5. Не пишите свою собственную лицензию.
  • Классифицировать свое программное обеспечение, используя систему классификации PyPI. Я объясню, что это значит позже в этой главе.
  • Написать файл «прочти меня» (read me). Не экономьте на этом. Как минимум, он должен дать вашим пользователям обзор того, что делает ваше программное обеспечение и как его установить.

16.3 Структура каталогов

Чтобы начать создавать пакет программного обеспечения на Python, вам нужно привести в порядок файлы и каталоги. Каталог httplib2 выглядит так:

httplib2/                 (1)
|
+--README.txt             (2)
|
+--setup.py               (3)
|
+--httplib2/              (4)
   |
   +--__init__.py
   |
   +--iri2uri.py
  1. Создайте корневой каталог для хранения всего. Дайте ему то же имя, что и вашему модулю на Python.
  2. Для удобства пользователей Windows ваш файл «readme» должен иметь расширение .txt и использовать символ возврата каретки. То, что вы используете нестандартный текстовый редактор, который запускается из командной строки и включает в себя собственный язык макросов, не означает, что вам нужно усложнить жизнь своим пользователям (ваши пользователи используют Notepad; грустно но это так). Даже если вы работаете в Linux или Mac OS X, ваш модный текстовый редактор, несомненно, имеет возможность сохранять файлы, используя символы возврата каретки в стиле Windows.
  3. Ваш скрипт Distutils для установки должен называться setup.py, если у вас нет веских причин так не делать. У вас нет веских причин так не делать.
  4. Если ваше программное обеспечение на Python представляет собой один файл .py, вы должны поместить его в корневой каталог вместе с файлом «readme» и скриптом установки. Но httplib2 – это не один файл .py; это многофайловый модуль. Но это нормально! Просто поместите каталог httplib2 в корневой каталог, чтобы у вас был файл __init__.py в каталоге httplib2/ в корневом каталоге httplib2/. Это не проблема; на самом деле это упростит процесс упаковки.

Каталог chardet выглядит немного иначе. Как и httplib2, это многофайловый модуль, поэтому в корневом каталоге chardet/ находится каталог chardet/. В дополнение к файлу README.txt, chardet содержит документацию в формате HTML в каталоге docs/. Каталог docs/ содержит несколько файлов .html и .css и подкаталог images/, который содержит несколько файлов .png и .gif (это будет важно позднее). Также, в соответствии с соглашением для (L)GPL-лицензированного программного обеспечения, у него есть отдельный файл с именем COPYING.txt, который содержит полный текст LGPL.

chardet/
|
+--COPYING.txt
|
+--setup.py
|
+--README.txt
|
+--docs/
|  |
|  +--index.html
|  |
|  +--usage.html
|  |
|  +--images/ ...
|
+--chardet/
   |
   +--__init__.py
   |
   +--big5freq.py
   |
   +--...

16.4 Написание скрипта установки

Скрипт установки Distutils – это скрипт на Python. Теоретически, он может делать всё, что может делать Python. На практике он должен быть как можно меньше, и как можно более стандартным. Скрипты установки должны быть скучными. Чем более экзотичен процесс установки, тем более экзотичны будут ваши сообщения об ошибках.

Первая строка каждого скрипта установки Distutils всегда одинакова:

from distutils.core import setup

Это импортирует функцию setup(), которая является основной точкой входа в Distutils. 95% всех скриптов установки Distutils состоят из одного вызова setup(), и ничего более. (Я только что придумал эту статистику, но если ваш скрипт установки Distutils делает больше, чем просто вызывает функцию Distutils setup(), у вас должна быть веская причина. У вас есть веская причина? Не думаю.)

Функция setup()может принимать десятки параметров. Чтобы все вовлеченные участники понимали, о чем идет речь, для каждого параметра вы должны использовать именованные аргументы. Это не просто соглашение; это обязательное требование. Ваш скрипт установки завершится сбоем, если вы попытаетесь вызвать функцию setup() с неименованными аргументами.

Следующие именованные аргументы обязательны:

  • name, название пакета;
  • version, номер версии пакета;
  • author, ваше полное имя;
  • author_email, ваш адрес электронной почты;
  • url, домашняя страница вашего проекта. Если у вас нет отдельного веб-сайта для проекта, то это может быть ваша страница пакета на PyPI,.

Хотя это и не обязательно, я рекомендую также включить в скрипт установки следующее:

  • description, однострочное описание проекта.
  • long_description, многострочное описание в формате reStructuredText. PyPI преобразует его в HTML и покажет его на странице вашего пакета.
  • classifiers, список специально отформатированных строк, описанных в следующем разделе.

Метаданные скрипта установки определены в PEP 314.

Теперь давайте посмотрим на скрипт установки chardet. В нем есть все эти обязательные и рекомендуемые параметры, плюс один, который я еще не упомянул: packages.

from distutils.core import setup
setup(
    name = 'chardet',
    packages = ['chardet'],
    version = '1.0.2',
    description = 'Universal encoding detector',
    author='Mark Pilgrim',
    ...
)

Параметр packages указывает на неудачное совпадение слов в процессе создания дистрибутива. Мы говорим о «пакете» как о том, что вы создаете (и, возможно, включаете его в Python “Package” Index). Но этот параметр packages относится не к этому. Он относится к тому факту, что модуль chardet является многофайловым модулем, иногда называемым… «пакетом». Параметр packages указывает Distutils включить каталог chardet/, его файл __init__.py и все другие файлы .py, которые составляют модуль chardet. Это очень важно; все эти счастливые разговоры о документации и метаданных не имеют значения, если вы забудете включить реальный код!

16.5 Классификация вашего пакета

Python Package Index (PyPI) содержит тысячи библиотек на Python. Правильные метаданные классификации упростят людям поиск ваших проектов. PyPI позволяет просматривать пакеты по классификатору. Вы даже можете выбрать несколько классификаторов, чтобы сузить область поиска. Классификаторы – это не невидимые метаданные, которые вы можете просто игнорировать!

Чтобы классифицировать ваше программное обеспечение, передайте параметр classifiers функции setup() Distutils. Параметр classifiers представляет собой список строк. Эти строки не являются произвольными. Все строки классификатора должны браться из этого списка на PyPI.

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

  • Programming Language (язык программирования). В частности, вы должны включить и «Programming Language :: Python«, и «Programming Language :: Python :: 3«. Если вы не включите их, ваш пакет не будет отображаться в этом списке библиотек, совместимых с Python 3.
  • License (лицензия). Это первое, на что я обращаю внимание при оценке сторонних библиотек. Не заставляйте меня охотиться за этой важной информацией. Не включайте более одного классификатора лицензии, если ваше программное обеспечение явно не доступно под несколькими лицензиями. (И не выпускайте программное обеспечение под несколькими лицензиями, если не обязаны это делать. И не заставляйте других людей делать это. Лицензирование – достаточная головная боль; не усугубляйте еще больше.)
  • Operating System (операционная система). Если ваше программное обеспечение работает только в Windows (или Mac OS X, или Linux), я хочу узнать об этом раньше, а не позже. Если ваше программное обеспечение работает везде без какого-либо платформозависимого кода, используйте классификатор «Operating System :: OS Independent«. Несколько классификаторов Operating System необходимы только в том случае, если вашему программному обеспечению требуется конкретная поддержка для каждой платформы (это не распространено).

Я также рекомендую вам включить следующие классификаторы:

  • Development Status (состояние разработки). Ваше программное обеспечение в версии бета? В версии альфа? Пре-альфа? Выбери один из вариантов. Будьте честны.
  • Intended Audience (целевая аудитория). Кто будет загружать ваше программное обеспечение? Наиболее распространенными вариантами являются Developers (разработчики), End Users/Desktop (конечные пользователи / десктоп), Science/Research (наука/исследования) and System Administrators (системные администраторы).
  • Framework (фреймворк). Если ваше программное обеспечение является плагином для более крупного фреймворка Python, такого как Django или Zope, включите соответствующий классификатор Framework. Если нет, пропустите его.
  • Topic (тема). Есть большое количество тем на выбор; выберите всё, что подходит.

16.5.1 Примеры хороших классификаторов пакетов

В качестве примера, вот классификаторы для Django, готового к работе, кроссплатформенного, лицензированного под BSD фреймворка веб-приложений, который работает на вашем веб-сервере.

Development Status :: 5 - Production/Stable
Environment :: Web Environment
Framework :: Django
Intended Audience :: Developers
License :: OSI Approved :: BSD License
Operating System :: OS Independent
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3 :: Only
Topic :: Internet :: WWW/HTTP
Topic :: Internet :: WWW/HTTP :: Dynamic Content
Topic :: Internet :: WWW/HTTP :: WSGI
Topic :: Software Development :: Libraries :: Application Frameworks
Topic :: Software Development :: Libraries :: Python Modules

Вот классификаторы для chardet, библиотеки определения кодировки символов, описанной в главе 15 «Учебный пример: портирование chardet на Python 3». chardet – в бета-версии, кроссплатформенная, совместимая с Python 3, лицензия LGPL, и предназначена для разработчиков, чтобы интегрировать в свои собственные продукты.

Programming Language :: Python
Programming Language :: Python :: 3
License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
Operating System :: OS Independent
Development Status :: 4 - Beta
Environment :: Other Environment
Intended Audience :: Developers
Topic :: Text Processing :: Linguistic
Topic :: Software Development :: Libraries :: Python Modules

А вот классификаторы для httplib2, библиотеки, представленной в главе 14 «HTTP веб-сервисы». httplib2 – в бета-версии, кроссплатформенная, с лицензией MIT, предназначена для разработчиков на Python.

Programming Language :: Python
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
Development Status :: 4 - Beta
Environment :: Web Environment
Intended Audience :: Developers
Topic :: Internet :: WWW/HTTP
Topic :: Software Development :: Libraries :: Python Modules

16.6 Указание дополнительных файлов с помощью манифеста

По умолчанию Distutils будет включать в ваш пакет следующие файлы:

  • README.txt
  • setup.py
  • Файлы .py, необходимые для многофайловых модулей, перечисленных в параметре packages
  • Отдельные .py файлы, перечисленные в параметре py_modules

Это охватывает все файлы в проекте httplib2. Но для проекта chardet мы также хотим включить файл лицензии COPYING.txt и весь каталог docs/, содержащий изображения и HTML файлы. Чтобы указать Distutils, чтобы он при сборке пакета chardet включил эти дополнительные файлы и каталоги, вам понадобится файл манифеста.

Файл манифеста – это текстовый файл с именем MANIFEST.in. Поместите его в корневой каталог проекта, рядом с README.txt и setup.py. Файлы манифеста – это не скрипты Python; это текстовые файлы, которые содержат серию «команд» в формате, определенном Distutils. Команды манифеста позволяют включать или исключать определенные файлы и каталоги.

Это весь файл манифеста для проекта chardet:

include COPYING.txt                                (1)
recursive-include docs *.html *.css *.png *.gif    (2)
  1. Строка 1. Первая строка не требует пояснений: включить файл COPYING.txt из корневого каталога проекта.
  2. Строка 2. Вторая строка немного сложнее. Команда recursive-include принимает имя каталога и одно или несколько имен файлов. Имена файлов не ограничены конкретными файлами; они могут включать подстановочные знаки. Эта строка означает «Видите этот каталог docs/ в корневом каталоге проекта? Ищите там (рекурсивно) файлы .html, .css, .png и .gif. Я хочу, чтобы все они были в релизе моего пакета.»

Все команды манифеста сохраняют структуру каталогов, заданную вами в каталоге вашего проекта. Эта команда recursive-include не собирается помещать кучу файлов .html и .png в корневой каталог выпускаемого пакета. Она сохранит существующую структуру каталога docs/, но включая в себя только те файлы в этом каталоге, которые соответствуют заданным подстановочным символам. (Я не упоминал об этом ранее, но документация chardet на самом деле написана в формате XML и преобразована в HTML отдельным скриптом. Я не хочу включать файлы XML в релиз пакета, мне нужны только HTML и изображения.)

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

16.7 Проверка вашего скрипта установки на наличие ошибок

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

c:Userspilgrimchardet> c:python31python.exe setup.py check
running check
warning: check: missing required meta-data: version

После того, как вы добавите параметр version (и все остальные необходимые метаданные), результат команды check будет выглядеть следующим образом:

c:Userspilgrimchardet> c:python31python.exe setup.py check
running check

16.8 Создание дистрибутива исходников

Distutils поддерживает сборку различных типов пакетов. Как минимум, вы должны создать «дистрибутив исходников», который содержит ваш исходный код, ваш скрипт установки Distutils, ваш файл «read me» и все дополнительные файлы, которые вы хотите включить. Чтобы создать дистрибутив исходников, передайте в ваш скрипт установки Distutils команду sdist.

c:Userspilgrimchardet> c:python31python.exe setup.py sdist
running sdist
running check
reading manifest template 'MANIFEST.in'
writing manifest file 'MANIFEST'
creating chardet-1.0.2
creating chardet-1.0.2chardet
creating chardet-1.0.2docs
creating chardet-1.0.2docsimages
copying files to chardet-1.0.2...
copying COPYING -> chardet-1.0.2
copying README.txt -> chardet-1.0.2
copying setup.py -> chardet-1.0.2
copying chardet__init__.py -> chardet-1.0.2chardet
copying chardetbig5freq.py -> chardet-1.0.2chardet
...
copying chardetuniversaldetector.py -> chardet-1.0.2chardet
copying chardetutf8prober.py -> chardet-1.0.2chardet
copying docsfaq.html -> chardet-1.0.2docs
copying docshistory.html -> chardet-1.0.2docs
copying docshow-it-works.html -> chardet-1.0.2docs
copying docsindex.html -> chardet-1.0.2docs
copying docslicense.html -> chardet-1.0.2docs
copying docssupported-encodings.html -> chardet-1.0.2docs
copying docsusage.html -> chardet-1.0.2docs
copying docsimagescaution.png -> chardet-1.0.2docsimages
copying docsimagesimportant.png -> chardet-1.0.2docsimages
copying docsimagesnote.png -> chardet-1.0.2docsimages
copying docsimagespermalink.gif -> chardet-1.0.2docsimages
copying docsimagestip.png -> chardet-1.0.2docsimages
copying docsimageswarning.png -> chardet-1.0.2docsimages
creating dist
creating 'distchardet-1.0.2.zip' and adding 'chardet-1.0.2' to it
adding 'chardet-1.0.2COPYING'
adding 'chardet-1.0.2PKG-INFO'
adding 'chardet-1.0.2README.txt'
adding 'chardet-1.0.2setup.py'
adding 'chardet-1.0.2chardetbig5freq.py'
adding 'chardet-1.0.2chardetbig5prober.py'
...
adding 'chardet-1.0.2chardetuniversaldetector.py'
adding 'chardet-1.0.2chardetutf8prober.py'
adding 'chardet-1.0.2chardet__init__.py'
adding 'chardet-1.0.2docsfaq.html'
adding 'chardet-1.0.2docshistory.html'
adding 'chardet-1.0.2docshow-it-works.html'
adding 'chardet-1.0.2docsindex.html'
adding 'chardet-1.0.2docslicense.html'
adding 'chardet-1.0.2docssupported-encodings.html'
adding 'chardet-1.0.2docsusage.html'
adding 'chardet-1.0.2docsimagescaution.png'
adding 'chardet-1.0.2docsimagesimportant.png'
adding 'chardet-1.0.2docsimagesnote.png'
adding 'chardet-1.0.2docsimagespermalink.gif'
adding 'chardet-1.0.2docsimagestip.png'
adding 'chardet-1.0.2docsimageswarning.png'
removing 'chardet-1.0.2' (and everything under it)

Несколько замечаний:

  • Distutils заметил файл манифеста (MANIFEST.in).
  • Distutils успешно проанализировал файл манифеста и добавил нужные нам файлы: COPYING.txt, а также HTML файлы и изображения в каталоге docs/.
  • Если вы загляните в каталог вашего проекта, вы увидите, что Distutils создал каталог dist/. В этом каталоге dist/ находится .zip-файл, который вы можете распространять.
c:Userspilgrimchardet> dir dist
 Volume in drive C has no label.
 Volume Serial Number is DED5-B4F8

 Directory of c:Userspilgrimchardetdist

07/30/2009  06:29 PM    <DIR>          .
07/30/2009  06:29 PM    <DIR>          ..
07/30/2009  06:29 PM           206,440 chardet-1.0.2.zip
               1 File(s)        206,440 bytes
               2 Dir(s)  61,424,635,904 bytes free

16.9 Создание графического установщика

По-моему, каждая библиотека Python заслуживает наличие графического установщика для пользователей Windows. Его легко обеспечить (даже если вы сами не работаете под Windows), а пользователи Windows это ценят.

Distutils может создать для вас графический установщик Windows, если передадите в ваш скрипт установки Distutils команду bdist_wininst.

c:Userspilgrimchardet> c:python31python.exe setup.py bdist_wininst
running bdist_wininst
running build
running build_py
creating build
creating buildlib
creating buildlibchardet
copying chardetbig5freq.py -> buildlibchardet
copying chardetbig5prober.py -> buildlibchardet
...
copying chardetuniversaldetector.py -> buildlibchardet
copying chardetutf8prober.py -> buildlibchardet
copying chardet__init__.py -> buildlibchardet
installing to buildbdist.win32wininst
running install_lib
creating buildbdist.win32
creating buildbdist.win32wininst
creating buildbdist.win32wininstPURELIB
creating buildbdist.win32wininstPURELIBchardet
copying buildlibchardetbig5freq.py -> buildbdist.win32wininstPURELIBchardet
copying buildlibchardetbig5prober.py -> buildbdist.win32wininstPURELIBchardet
...
copying buildlibchardetuniversaldetector.py -> buildbdist.win32wininstPURELIBchardet
copying buildlibchardetutf8prober.py -> buildbdist.win32wininstPURELIBchardet
copying buildlibchardet__init__.py -> buildbdist.win32wininstPURELIBchardet
running install_egg_info
Writing buildbdist.win32wininstPURELIBchardet-1.0.2-py3.1.egg-info
creating 'c:userspilgrimappdatalocaltemptmp2f4h7e.zip' and adding '.' to it
adding 'PURELIBchardet-1.0.2-py3.1.egg-info'
adding 'PURELIBchardetbig5freq.py'
adding 'PURELIBchardetbig5prober.py'
...
adding 'PURELIBchardetuniversaldetector.py'
adding 'PURELIBchardetutf8prober.py'
adding 'PURELIBchardet__init__.py'
removing 'buildbdist.win32wininst' (and everything under it)
c:Userspilgrimchardet> dir dist
c:Userspilgrimchardet>dir dist
 Volume in drive C has no label.
 Volume Serial Number is AADE-E29F

 Directory of c:Userspilgrimchardetdist

07/30/2009  10:14 PM    <DIR>          .
07/30/2009  10:14 PM    <DIR>          ..
07/30/2009  10:14 PM           371,236 chardet-1.0.2.win32.exe
07/30/2009  06:29 PM           206,440 chardet-1.0.2.zip
               2 File(s)        577,676 bytes
               2 Dir(s)  61,424,070,656 bytes free

16.9.1 Сборка устанавливаемых пакетов для других операционных систем

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

Например, моя библиотека chardet находится в репозиториях Debian GNU/Linux (и, следовательно, в репозиториях Ubuntu). Я не имел ничего общего с этим; пакеты просто появились там однажды. Сообщество Debian имеет свои собственные политики для создания пакетов библиотек Python, а пакет Debian python-chardet разработан в соответствии с этими соглашениями. А поскольку пакет находится в репозиториях Debian, пользователи Debian будут получать обновления безопасности и/или новые версии в зависимости от общесистемных настроек, выбранных ими для управления своими компьютерами.

Пакеты Linux, которые собирает Distutils, не предлагают ни одно из этих преимуществ. Лучше потратить время на что-то другое.

16.10 Добавление вашего программного обеспечения в Python Package Index

Загрузка программного обеспечения в Python Package Index состоит из трех этапов.

  1. зарегистрируетесь сами;
  2. зарегистрируйте свое программное обеспечение;
  3. загрузите пакеты, которые вы создали с помощью setup.py sdist и setup.py bdist_ *.

Чтобы зарегистрироваться, перейдите на страницу регистрации пользователя PyPI. Введите имя пользователя и пароль, укажите действующий адрес электронной почты и нажмите кнопку «Create account». (Если у вас есть ключ PGP или GPG, можете также предоставить его. Если у вас его нет или вы не знаете, что это такое, то не беспокойтесь об этом.) Проверьте свою электронную почту; в течение нескольких минут вы получите сообщение от PyPI со ссылкой для проверки. Нажмите на ссылку, чтобы завершить процесс регистрации.

Теперь вам нужно зарегистрировать свое программное обеспечение в PyPI и загрузить его. Вы можете сделать всё это за один шаг.

c:Userspilgrimchardet> c:python31python.exe setup.py register sdist bdist_wininst upload  ①
running register
We need to know who you are, so please choose either:
 1. use your existing login,
 2. register as a new user,
 3. have the server generate a new password for you (and email it to you), or
 4. quit
Your selection [default 1]:  1                                                                 ②
Username: MarkPilgrim                                                                          ③
Password:
Registering chardet to http://pypi.python.org/pypi                                             ④
Server response (200): OK
running sdist                                                                                  ⑤
... output trimmed for brevity ...
running bdist_wininst                                                                          ⑥
... output trimmed for brevity ...
running upload                                                                                 ⑦
Submitting distchardet-1.0.2.zip to http://pypi.python.org/pypi
Server response (200): OK
Submitting distchardet-1.0.2.win32.exe to http://pypi.python.org/pypi
Server response (200): OK
I can store your PyPI login so future submissions will be faster.
(the login will be stored in c:home.pypirc)
Save your login (y/N)?n                                                                        ⑧
  1. Строка 1. Когда вы публикуете свой проект впервые, Distutils добавит ваше программное обеспечение в Python Package Index и присвоит ему собственный URL. Каждый раз после этого он будет просто обновлять метаданные проекта с любыми изменениями, которые вы могли внести в параметры setup.py. Затем он создает дистрибутив исходного кода (sdist) и установщик Windows (bdist_wininst), а затем загружает их в PyPI (upload).
  2. Строка 8. Введите 1 или просто нажмите ENTER, чтобы выбрать «использовать существующий логин».
  3. Строка 9. Введите имя пользователя и пароль, которые вы выбрали на странице регистрации пользователя PyPI. Distuils не будет выводить ваш пароль; он даже не будет отражать звездочки вместо символов. Просто введите свой пароль и нажмите клавишу ENTER.
  4. Строка 11. Distutils регистрирует ваш пакет в Python Package Index…
  5. Строка 13. … собирает ваш дистрибутив исходного кода…
  6. Строка 15. … собирает ваш установщик Windows…
  7. Строка 17. … и загружает их обоих в Python Package Index.
  8. Строка 24. Если вы хотите автоматизировать процесс релиза новых версий, то вам нужно сохранить свои учетные данные PyPI в локальном файле. Это совершенно небезопасно и совершенно необязательно.

Поздравляем, теперь у вас есть собственная страница в Python Package Index! Ее адрес: http://pypi.python.org/pypi/NAME, где NAME – это строка, которую вы передали в параметре name в файле setup.py.

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

c:Userspilgrimchardet> c:python31python.exe setup.py register sdist bdist_wininst upload

16.11 Множество возможных вариантов создания пакетов Python

Distutils не является единственным инструментом создания пакетов Python, но на момент написания этой статьи (август 2009 года) это единственный фреймворк создания пакетов, который работает в Python 3. Существует ряд других платформ для Python 2; некоторые фокусируются на установке, другие – на тестировании и развертывании. Некоторые или все из них могут в конечном итоге быть перенесены на Python 3 в будущем.

Эти фреймворки ориентированы на установку:

  • Setuptools (портирован)
  • Pip (портирован)
  • Distribute

Эти сосредоточены на тестировании и развертывании:

  • virtualenv (портирован)
  • zc.buildout (портирован)
  • Paver
  • Fabric (портирован)
  • py2exe (портирован)

16.12 Материалы для дальнейшего чтения

О Distutils:

  • Distributing Python Modules with Distutils
  • Core Distutils functionality список всех возможных аргументов функции setup()
  • Distutils Cookbook
  • PEP 370: Per user site-packages directory
  • PEP 370 and “environment stew”

О других фреймворках создания пакетов:

  • The Python packaging ecosystem
  • On packaging
  • A few corrections to “On packaging”
  • Why I like Pip
  • Python packaging: a few observations
  • Nobody expects Python packaging!

Теги

PythonВысокоуровневые языки программированияОбучениеЯзыки программирования

Python — отличный язык программирования, но упаковка — один из его слабых мест. Это общеизвестный факт в обществе. Установка, импорт, использование и создание пакетов значительно улучшились за эти годы, но это все еще не на одном уровне с новыми языками, такими как Go и Rust, которые многому научились из борьбы Python и других зрелых языков.

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

Как написать библиотеку Python

Библиотека Python — это связная коллекция модулей Python, организованная в виде пакета Python. В общем, это означает, что все модули находятся в одном каталоге и этот каталог находится в пути поиска Python.

Давайте быстро напишем небольшой пакет Python 3 и проиллюстрируем все эти концепции.

Пакет патологии

Python 3 имеет отличный объект Path, который является огромным улучшением по сравнению с неуклюжим модулем Python 2 os.path. Но ему не хватает одной важной возможности — найти путь к текущему сценарию. Это очень важно, когда вы хотите найти файлы доступа относительно текущего скрипта.

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

Вот как вы делаете это в Python:

1

2

3

import pathlib

script_dir = pathlib.Path(__file__).parent.resolve()

Для доступа к файлу с именем file.txt в подкаталоге data текущего каталога скрипта вы можете использовать следующий код: print(open(str(script_dir/'data/file.txt').read())

С пакетом pathology у вас есть встроенный метод script_dir , и вы используете его следующим образом:

1

2

3

from pathology.Path import script_dir

print(open(str(script_dir()/’data/file.txt’).read())

Да, это полный рот. Пакет патологии очень прост. Он извлекает свой собственный класс Path из Pathlib’s Path и добавляет статический script_dir (), который всегда возвращает путь вызывающего скрипта.

Вот реализация:

1

2

3

4

5

6

7

8

9

import pathlib

import inspect

class Path(type(pathlib.Path())):

    @staticmethod

    def script_dir():

        print(inspect.stack()[1].filename)

        p = pathlib.Path(inspect.stack()[1].filename)

        return p.parent.resolve()

Из-за кросс-платформенной реализации pathlib.Path , вы можете наследовать его напрямую и должны наследовать от определенного подкласса ( PosixPath или WindowsPath ). Разрешение dir скрипта использует модуль inspect для поиска вызывающего абонента, а затем его атрибута имени файла.

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

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

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import os

import shutil

from unittest import TestCase

from pathology.path import Path

class PathTest(TestCase):

    def test_script_dir(self):

        expected = os.path.abspath(os.path.dirname(__file__))

        actual = str(Path.script_dir())

        self.assertEqual(expected, actual)

    def test_file_access(self):

        script_dir = os.path.abspath(os.path.dirname(__file__))

        subdir = os.path.join(script_dir, ‘test_data’)

        if Path(subdir).is_dir():

            shutil.rmtree(subdir)

        os.makedirs(subdir)

        file_path = str(Path(subdir)/’file.txt’)

        content = ‘123’

        open(file_path, ‘w’).write(content)

        test_path = Path.script_dir()/subdir/’file.txt’

        actual = open(str(test_path)).read()

        self.assertEqual(content, actual)

Путь Питона

Пакеты Python должны быть установлены где-то на пути поиска Python для импорта модулями Python. Путь поиска Python представляет собой список каталогов и всегда доступен в sys.path . Вот мой текущий sys.path:

1

2

3

4

5

6

7

>>> print(‘n’.join(sys.path))

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python36.zip

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/lib-dynload

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages

/Users/gigi.sayfan/miniconda3/envs/py3/lib/python3.6/site-packages/setuptools-27.2.0-py3.6.egg

Обратите внимание, что первая пустая строка вывода представляет текущий каталог, поэтому вы можете импортировать модули из текущего рабочего каталога, каким бы он ни был. Вы можете напрямую добавлять или удалять каталоги в / из sys.path.

Вы также можете определить переменную среды PYTHONPATH , и есть несколько других способов управления ею. Стандартные site-packages включены по умолчанию, и именно здесь вы устанавливаете пакеты с помощью pip go.

Как упаковать библиотеку Python

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

Чтобы создать бинарный дистрибутив, называемый колесом, вы запускаете: python setup.py bdist_wheel

Вот файл setup.py пакета патологии:

01

02

03

04

05

06

07

08

09

10

11

12

from setuptools import setup, find_packages

setup(name=’pathology’,

      version=’0.1′,

      url=’https://github.com/the-gigi/pathology’,

      license=’MIT’,

      author=’Gigi Sayfan’,

      author_email=’the.gigi@gmail.com’,

      description=’Add static script_dir() method to Path’,

      packages=find_packages(exclude=[‘tests’]),

      long_description=open(‘README.md’).read(),

      zip_safe=False)

Он включает в себя множество метаданных в дополнение к элементу «packages», который использует find_packages() импортированную из setuptools для поиска find_packages() .

Давайте создадим исходный дистрибутив:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

$ python setup.py sdist

running sdist

running egg_info

creating pathology.egg-info

writing pathology.egg-info/PKG-INFO

writing dependency_links to pathology.egg-info/dependency_links.txt

writing top-level names to pathology.egg-info/top_level.txt

writing manifest file ‘pathology.egg-info/SOURCES.txt’

reading manifest file ‘pathology.egg-info/SOURCES.txt’

writing manifest file ‘pathology.egg-info/SOURCES.txt’

warning: sdist: standard file not found: should have one of README, README.rst, README.txt

running check

creating pathology-0.1

creating pathology-0.1/pathology

creating pathology-0.1/pathology.egg-info

copying files to pathology-0.1…

copying setup.py -> pathology-0.1

copying pathology/__init__.py -> pathology-0.1/pathology

copying pathology/path.py -> pathology-0.1/pathology

copying pathology.egg-info/PKG-INFO -> pathology-0.1/pathology.egg-info

copying pathology.egg-info/SOURCES.txt -> pathology-0.1/pathology.egg-info

copying pathology.egg-info/dependency_links.txt -> pathology-0.1/pathology.egg-info

copying pathology.egg-info/not-zip-safe -> pathology-0.1/pathology.egg-info

copying pathology.egg-info/top_level.txt -> pathology-0.1/pathology.egg-info

Writing pathology-0.1/setup.cfg

creating dist

Creating tar archive

removing ‘pathology-0.1’ (and everything under it)

Предупреждение связано с тем, что я использовал нестандартный файл README.md. Это безопасно игнорировать. Результатом является tar-gzipped файл в каталоге dist:

1

2

3

4

5

$ ls -la dist

total 8

drwxr-xr-x 3 gigi.sayfan gigi.sayfan 102 Apr 18 21:20 .

drwxr-xr-x 12 gigi.sayfan gigi.sayfan 408 Apr 18 21:20 ..

-rw-r—r— 1 gigi.sayfan gigi.sayfan 1223 Apr 18 21:20 pathology-0.1.tar.gz

А вот бинарный дистрибутив:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

$ python setup.py bdist_wheel

running bdist_wheel

running build

running build_py

creating build

creating build/lib

creating build/lib/pathology

copying pathology/__init__.py -> build/lib/pathology

copying pathology/path.py -> build/lib/pathology

installing to build/bdist.macosx-10.7-x86_64/wheel

running install

running install_lib

creating build/bdist.macosx-10.7-x86_64

creating build/bdist.macosx-10.7-x86_64/wheel

creating build/bdist.macosx-10.7-x86_64/wheel/pathology

copying build/lib/pathology/__init__.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology

copying build/lib/pathology/path.py -> build/bdist.macosx-10.7-x86_64/wheel/pathology

running install_egg_info

running egg_info

writing pathology.egg-info/PKG-INFO

writing dependency_links to pathology.egg-info/dependency_links.txt

writing top-level names to pathology.egg-info/top_level.txt

reading manifest file ‘pathology.egg-info/SOURCES.txt’

writing manifest file ‘pathology.egg-info/SOURCES.txt’

Copying pathology.egg-info to build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1-py3.6.egg-info

running install_scripts

creating build/bdist.macosx-10.7-x86_64/wheel/pathology-0.1.dist-info/WHEEL

Пакет pathology содержит только чистые модули Python, поэтому можно создать универсальный пакет. Если ваш пакет включает расширения C, вам придется создать отдельное колесо для каждой платформы:

1

2

3

4

5

6

$ ls -la dist

total 16

drwxr-xr-x 4 gigi.sayfan gigi.sayfan 136 Apr 18 21:24 .

drwxr-xr-x 13 gigi.sayfan gigi.sayfan 442 Apr 18 21:24 ..

-rw-r—r— 1 gigi.sayfan gigi.sayfan 2695 Apr 18 21:24 pathology-0.1-py3-none-any.whl

-rw-r—r— 1 gigi.sayfan gigi.sayfan 1223 Apr 18 21:20 pathology-0.1.tar.gz

Чтобы глубже погрузиться в тему упаковки библиотек Python, ознакомьтесь с разделом Как написать свой собственный пакет Python .

Как распространять пакет Python

Python имеет центральное хранилище пакетов, называемое PyPI (индекс пакетов Python). Когда вы устанавливаете пакет Python с помощью pip, он загружает пакет из PyPI (если вы не укажете другой репозиторий). Чтобы распространять наш пакет патологий, нам нужно загрузить его в PyPI и предоставить некоторые дополнительные метаданные, необходимые PyPI. Шаги:

  • Создайте аккаунт на PyPI (только один раз).
  • Зарегистрируйте свой пакет.
  • Загрузите свой пакет.

Завести аккаунт

Вы можете создать учетную запись на сайте PyPI . Затем создайте файл .pypirc в вашем домашнем каталоге:

1

2

3

4

5

6

[distutils]

index-servers=pypi

[pypi]

repository = https://pypi.python.org/pypi

username = the_gigi

В целях тестирования вы можете добавить индексный сервер «pypitest» к вашему. файл pypirc :

01

02

03

04

05

06

07

08

09

10

11

12

[distutils]

index-servers=

    pypi

    pypitest

[pypitest]

repository = https://testpypi.python.org/pypi

username = the_gigi

[pypi]

repository = https://pypi.python.org/pypi

username = the_gigi

Зарегистрируйте свой пакет

Если это первый выпуск вашего пакета, вам необходимо зарегистрировать его в PyPI. Используйте команду register из setup.py. Он попросит вас ввести пароль. Обратите внимание, что я указываю на тестовый репозиторий здесь:

01

02

03

04

05

06

07

08

09

10

11

12

$ python setup.py register -r pypitest

running register

running egg_info

writing pathology.egg-info/PKG-INFO

writing dependency_links to pathology.egg-info/dependency_links.txt

writing top-level names to pathology.egg-info/top_level.txt

reading manifest file ‘pathology.egg-info/SOURCES.txt’

writing manifest file ‘pathology.egg-info/SOURCES.txt’

running check

Password:

Registering pathology to https://testpypi.python.org/pypi

Server response (200): OK

Загрузить свой пакет

Теперь, когда пакет зарегистрирован, мы можем загрузить его. Я рекомендую использовать шпагат , который является более безопасным. Установите его, как обычно, используя pip install twine . Затем загрузите вашу посылку, используя шпагат, и введите свой пароль (отредактировано ниже):

1

2

3

4

5

6

$ twine upload -r pypitest -p <redacted> dist/*

Uploading distributions to https://testpypi.python.org/pypi

Uploading pathology-0.1-py3-none-any.whl

[================================] 5679/5679 — 00:00:02

Uploading pathology-0.1.tar.gz

[================================] 4185/4185 — 00:00:01

Чтобы глубже погрузиться в тему распространения ваших пакетов, ознакомьтесь с разделом Как поделиться своими пакетами Python .

Вывод

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

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

Трудно представить программу Python без набора операторов import. Но как опубликовать библиотеку, чтобы её также легко могли импортировать другие разработчики?

Благодаря импортированию, модули Python удобно использовать

Благодаря импортированию, модули Python удобно использовать

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

1. Создаём элементы библиотеки

Публикация пакета требует знания некоторых деталей. В этом примере мы будем рассматривать предварительно опубликованный пакет под названием dist_alx. Чтобы вам было удобнее сверяться, эта директория доступна в виде zip-папки в репозитории на GitHub.

Каталог содержит все необходимые элементы, которые должен иметь пакет перед публикацией. Мы будем использовать этот пример в качестве эталона, поскольку все пакеты Python должны иметь одинаковую структуру. Если вам интересно, что именно делает пакет dist_alx, это объяснено там же в README-файле.

Корневой каталог dist_alx содержит следующие файлы и директории:

  • setup.py – содержит метаданные пакета,
  • setup.cfg – конфигурационный файл, используемый для хранения настроек,
  • подпапку с тем же именем, что и родительская папка (в данном примере dist_alx), где хранится фактический код вашего пакета на Python.

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

setup.py
        from setuptools import setup

setup(name='dist_alx',
      version='0.0',
      description='Gaussian and Binomial distributions',
      packages=['dist_alx'],
      author_email='mihajlovic.aleksa@gmail.com',
      zip_safe=False)
    
setup.cfg
        [egg_info]
tag_build = 
tag_date = 0

    

Любая публикуемая на PyPI библиотека обязана иметь три вышеуказанных элемента. Помимо этого, пакет должен выполнять следующие условия:

  • Уникальное имя библиотеки. Никакие два существующих пакета Python не могут одинаково называться.
  • Файл setup.py должен содержать параметры name и packages. Они также должны иметь то же имя, что и пакет (см. пример выше).
  • Параметр version: в случае если что-то в пакете изменилось, нужно изменить и значение version.
  • Файла setup.py должен иметь параметр author_email с адресом электронной почты для связи. Используйте действующий e-mail, это важно для дальнейшей регистрации программы в репозитории PyPI.

2. Подготавливаем код

Как указано выше, внутри вложенной папки должен находиться фактический код библиотеки. Если вы откроете подпапку dist_alx, вы увидите, что она содержит файл _init_.py. По умолчанию ядро ​​Python ищет файл _init_.py в качестве отправной точки при чтении кода. Файл _init_.py связан со всеми другими сценариями Python в подпапке. Например, в нашем файле _init_.py, есть строка импорта from .Gaussiandistribution import Gaussian. Все .py-файлы связаны. Хорошей идеей, прежде чем пытаться написать код пакета, будет обновить свои знания о классах Python.

Большинство общедоступных пакетов Python хранятся в репозитории PyPI. При установке пакета на свой компьютер инструкцией pip, вы фактически скачиваете его из репозитория PyPI. Соответственно для публикации нового пакета его нужно наоборот, загрузить на сервер PyPI. Чтобы опубликовать библиотеку, нужно завести аккаунт (это бесплатно). Адрес электронной почты должен быть тот же, что внутри setup.py в параметре author_email.

Скриншот окна регистрации в репозитории PyPI

Скриншот окна регистрации в репозитории PyPI

4. Публикуем библиотеку

Публикация осуществляется из командной строки или терминала. Команды идентичны в Windows и Linux.

Для публикации нам потребуется установить две библиотеки – setuptools и twine:

        pip install setuptools
    
        pip install twine
    

Переходим к родительскому каталогу.

Как опубликовать свою Python библиотеку на PyPI

Развёртываем пакет запустив setup.py:

        python setup.py sdist
    

Как опубликовать свою Python библиотеку на PyPI

Обратите внимание, что теперь в родительской папке будут созданы две новых директории (egg-info и dist).

Как опубликовать свою Python библиотеку на PyPI

Теперь с помощью twine развёртываем пакет на PyPI:

        twine upload dist/*
    

Как опубликовать свою Python библиотеку на PyPI

Здесь нужно указать своё имя пользователя и пароль PyPI.

Как опубликовать свою Python библиотеку на PyPI

Вуаля! Пакет размещён на сервере и готов к использованию!

Переходим в учётную запись на PyPI, идём в раздел Your projects. Если всё в порядке, вы увидите библиотеку.

Как опубликовать свою Python библиотеку на PyPI

Обратите внимание, что PyPI не поддерживает на сайте символ подчёркивания в именах файлов. Поэтому dist_alx отображается как dist-alx. Однако это не влияет на использование библиотеки – при последующем импорте мы будем вводить, как и задумано, dist_alx.

5. Используем

Переходим к любимому клиенту Python (например, Jupyter) и устанавливаем пакет с помощью pip. Импортируем и пользуемся в своё удовольствие!

Как опубликовать свою Python библиотеку на PyPI

Заключение

Прежде чем размещать пакет на главном сервере, опубликуйте его сначала на тестовом сервере PyPI.

Итак, последовательность создания библиотеки Python следующая:

  1. Изготовление необходимых элементов упаковки, проверка значений параметров.
  2. Подготовка кода пакета.
  3. Создание учётной записи PyPI (если её ещё не было).
  4. Публикация пакета на PyPI.
  5. Тестирование: pip-установка, импорт и запуск модуля.

Если вы думаете, что пока не готовы публиковать свою библиотеку, вам могут быть полезны такие наши публикации:

  • Погружаемся в основы и нюансы тестирования Python-кода
  • Инструменты для анализа кода Python. Часть 1
  • Инструменты для анализа кода Python. Часть 2
  • Python: практики для написания эффективного кода

Источники

  • https://towardsdatascience.com/make-your-own-python-package-6d08a400fc2d

Работа с модулями: создание, подключение инструкциями import и from

Модулем в Python называется любой файл с программой (да-да, все те программы, которые вы писали, можно назвать модулями). В этой статье мы поговорим о том, как создать модуль, и как подключить модуль, из стандартной библиотеки или написанный вами.

Каждая программа может импортировать модуль и получить доступ к его классам, функциям и объектам. Нужно заметить, что модуль может быть написан не только на Python, а например, на C или C++.

Подключение модуля из стандартной библиотеки

Подключить модуль можно с помощью инструкции import. К примеру, подключим модуль os для получения текущей директории:

После ключевого слова import указывается название модуля. Одной инструкцией можно подключить несколько модулей, хотя этого не рекомендуется делать, так как это снижает читаемость кода. Импортируем модули time и random.

После импортирования модуля его название становится переменной, через которую можно получить доступ к атрибутам модуля. Например, можно обратиться к константе e, расположенной в модуле math:

Стоит отметить, что если указанный атрибут модуля не будет найден, возбудится исключение AttributeError. А если не удастся найти модуль для импортирования, то ImportError.

Использование псевдонимов

Если название модуля слишком длинное, или оно вам не нравится по каким-то другим причинам, то для него можно создать псевдоним, с помощью ключевого слова as.

Теперь доступ ко всем атрибутам модуля math осуществляется только с помощью переменной m, а переменной math в этой программе уже не будет (если, конечно, вы после этого не напишете import math, тогда модуль будет доступен как под именем m, так и под именем math).

Инструкция from

Подключить определенные атрибуты модуля можно с помощью инструкции from. Она имеет несколько форматов:

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

Импортируемые атрибуты можно разместить на нескольких строках, если их много, для лучшей читаемости кода:

Второй формат инструкции from позволяет подключить все (точнее, почти все) переменные из модуля. Для примера импортируем все атрибуты из модуля sys:

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

Создание своего модуля на Python

Теперь пришло время создать свой модуль. Создадим файл mymodule.py, в которой определим какие-нибудь функции:

Теперь в этой же папке создадим другой файл, например, main.py:

Поздравляю! Вы сделали свой модуль! Напоследок отвечу ещё на пару вопросов, связанных с созданием модулей:

Как назвать модуль?

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

Я вижу, что есть некоторые встроенные пакеты, которые я могу импортировать из любого скрипта, например:

Как создать простой пакет и добавить его в системную библиотеку, чтобы я мог импортировать его как datetime в приведенном выше примере?

Вы пытаетесь создать модуль.

Начните с установки пакета setuptools ; на Windows или Linux вы должны иметь возможность набирать pip install setuptools на терминале, чтобы установить это. Теперь вы можете написать import setuptools в командной строке python без получения ошибки.

После этого настройте структуру каталогов, содержащую setup.py и папку для кода проекта. Каталог должен содержать файл __init__.py , который позволяет вам import каталог, как если бы он был файлом.

В setup.py отбросьте следующий контент:

В my_project/__init__.py отбросьте некоторые вещи, которые вы хотите импортировать. Скажем…

Теперь, чтобы установить проект на общесистемном уровне, запустите python setup.py install . Обратите внимание, что вам нужно запустить это как root, если вы работаете в Linux, поскольку вы вносите изменения в общесистемные библиотеки python.

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

Обратите внимание, что этого достаточно, чтобы рассказать вам, как сделать модуль, но есть один адский материал, который setuptools может сделать для вас. Взгляните на https://pythonhosted.org/setuptools/setuptools.html для получения дополнительной информации о строительных материалах и https://docs.python.org/2/tutorial/modules.html для получения дополнительной информации о том, как работают модули, Если вы хотите посмотреть на пакет, который (я надеюсь) достаточно прост, то я сделал модуль LazyLog пару недель назад в поезде, и вы можете использовать его для справки.

Быстрый способ, если вы просто делаете что-то для своего собственного использования и не беспокоитесь об упаковке, заключается в том, чтобы поместить модуль (который может быть таким же простым, как один файл) в каталог системных site-packages . (В системах на базе Debian вы, скорее всего, захотите использовать dist-packages ).

Чтобы узнать, где находится каталог site-packages / dist-packages , запустите Python и:

Обратите внимание на последний элемент в этом примере: /usr/lib/python3.4/site-packages . Это то, что вы ищете. Итак, в этом примере, если я сохраню следующее в /usr/lib/python3.4/site-packages/foo.py :

Затем из любой точки моей системы:

Если вам действительно нужен пакет, вы можете сделать это с помощью boost, что позволяет взаимодействовать с C++. Вы можете реализовать алгоритмы с помощью C++ и скомпилировать его как библиотеку Python. Однако он плохо документирован. И, как описал документ, C API должен быть основным вариантом. Boost построен на C API любым способом.

Образец: Я сделал это несколько лет назад в классе. Вы можете сделать: import tfidf .

Если вы просто хотите использовать модуль для личного использования, просто поместите его в папку и добавьте эту папку в переменную среды PYTHONPATH .

Например, создайте папку в домашнем каталоге с именем

/python-packages , затем добавьте следующую строку в ваш .bashrc (если вы используете bash):

Затем просто удалите все модули/пакеты, которые вы хотите сделать доступными в

Как создать свой первый open source проект на Python (17 шагов)

Каждый разработчик ПО должен знать как создать библиотеку с нуля. В процессе работы Вы можете многому научиться. Только не забудьте запастись временем и терпением.

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

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

Шаг 1: Составьте план

Мы планируем создать простую библиотеку для использования в Python. Данная библиотека позволит пользователю легко конвертировать блокнот Jupyter в HTML-файл или Python-скрипт.
Первая итерация нашей библиотеки позволит вызвать функцию, которая выведет определенное сообщение.

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

Шаг 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. Вы можете создать репозиторий под своей личной учетной записью, но одна из целей работы — научиться создавать проект с открытым исходным кодом для более широкого сообщества.

image

Шаг 5: Настройте GitHub Repo

Создайте новый репозиторий. Я назвал свой notebookc.

image

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

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

Для этого проекта я выбрал третью версию Открытого лицензионного соглашения GNU, потому что она популярная, проверенная и “гарантирует пользователям свободу использования, изучения, обмена и изменения программного обеспечения” — источник.

image

Шаг 6: Клонируйте и добавьте директории

Выберите, куда Вы хотите клонировать Ваш репозиторий или выполните следующую функцию:

git clone https://github.com/notebooktoall/notebookc.git

Подставьте свою организацию и репозиторий.

Перейдите в папку проекта с помощью десктопного графического интерфейса или редактора кода. Или используйте командную строку с 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 шагов к рабочей библиотеке

  1. Составьте план.
  2. Дайте имя библиотеке.
  3. Настройте среду.
  4. Создайте организацию в GitHub.
  5. Настройте GitHub Repo.
  6. Клонируйте и добавьте директории.
  7. Скачайте и установите requirements_dev.txt.
  8. Поработайте с кодом.
  9. Создайте setup.py.
  10. Соберите первую версию.
  11. Создайте учётную запись TestPyPI.
  12. Опубликуйте библиотеку в PyPI.
  13. Проверьте и используйте установленную библиотеку.
  14. Залейте код на PyPI.
  15. Залейте библиотеку на GitHub.
  16. Создайте и объедините PR.
  17. Обновите рабочую версию на GitHub.

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:

Вопрос:

Я вижу, что есть некоторые встроенные пакеты, которые я могу импортировать из любого скрипта, например:

from datetime import date

today = date.today()
print today

Как создать простой пакет и добавить его в системную библиотеку, чтобы я мог импортировать его как datetime в приведенном выше примере?

Лучший ответ:

Вы пытаетесь создать модуль.

Начните с установки пакета setuptools; на Windows или Linux вы должны иметь возможность набирать pip install setuptools на терминале, чтобы установить это. Теперь вы можете написать import setuptools в командной строке python без получения ошибки.

После этого настройте структуру каталогов, содержащую setup.py и папку для кода проекта. Каталог должен содержать файл __init__.py, который позволяет вам import каталог, как если бы он был файлом.

some_folder/
|    setup.py
|    my_project/__init__.py

В setup.py отбросьте следующий контент:

# setup.py
from setuptools import setup

setup(name="My Awesome Project",
      version="0.0",
      packages=["my_project"])

В my_project/__init__.py отбросьте некоторые вещи, которые вы хотите импортировать. Скажем…

# my_project/__init__.py
greeting = "Hello world!"

Теперь, чтобы установить проект на общесистемном уровне, запустите python setup.py install. Обратите внимание, что вам нужно запустить это как root, если вы работаете в Linux, поскольку вы вносите изменения в общесистемные библиотеки python.

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

>>> from my_project import greeting
>>> print greeting
Hello world!
>>>

Обратите внимание, что этого достаточно, чтобы рассказать вам, как сделать модуль, но есть один адский материал, который setuptools может сделать для вас. Взгляните на https://pythonhosted.org/setuptools/setuptools.html для получения дополнительной информации о строительных материалах и https://docs.python.org/2/tutorial/modules.html для получения дополнительной информации о том, как работают модули, Если вы хотите посмотреть на пакет, который (я надеюсь) достаточно прост, то я сделал модуль LazyLog пару недель назад в поезде, и вы можете использовать его для справки.

Ответ №1

Быстрый способ, если вы просто делаете что-то для своего собственного использования и не беспокоитесь об упаковке, заключается в том, чтобы поместить модуль (который может быть таким же простым, как один файл) в каталог системных site-packages. (В системах на базе Debian вы, скорее всего, захотите использовать dist-packages).

Чтобы узнать, где находится каталог site-packages/dist-packages, запустите Python и:

>>> from sys import path
>>> path
['', '/usr/lib/python3.4/site-packages/pip-7.1.2-py3.4.egg', '/usr/lib/python34.zip', '/usr/lib/python3.4', '/usr/lib/python3.4/plat-cygwin', '/usr/lib/python3.4/lib-dynload', '/usr/lib/python3.4/site-packages']

Обратите внимание на последний элемент в этом примере: /usr/lib/python3.4/site-packages. Это то, что вы ищете. Итак, в этом примере, если я сохраню следующее в /usr/lib/python3.4/site-packages/foo.py:

def bar():
print('Hello world!')

Затем из любой точки моей системы:

>>> from foo import bar
>>> bar()
Hello world!

Ответ №2

Если вам действительно нужен пакет, вы можете сделать это с помощью boost, что позволяет взаимодействовать с C++. Вы можете реализовать алгоритмы с помощью C++ и скомпилировать его как библиотеку Python. Однако он плохо документирован. И, как описал документ, C API должен быть основным вариантом. Boost построен на C API любым способом.

Образец: Я сделал это несколько лет назад в классе. Вы можете сделать: import tfidf.

Ответ №3

Если вы просто хотите использовать модуль для личного использования, просто поместите его в папку и добавьте эту папку в переменную среды PYTHONPATH.

Например, создайте папку в домашнем каталоге с именем ~/python-packages, затем добавьте следующую строку в ваш .bashrc (если вы используете bash):

 export PYTHONPATH=$HOME/python-packages'

Затем просто удалите все модули/пакеты, которые вы хотите сделать доступными в ~/python-packages.

Ответ №4

Добавьте скрипт python или путь пакета к sys.path или просто переместите их в одно из мест в sys.path. НО я не предлагаю это делать…

Понравилась статья? Поделить с друзьями:
  • Как написать библиографию
  • Как написать библиографическое описание статьи
  • Как написать библиографическое описание книги
  • Как написать библиографический список интернет ресурсов
  • Как написать бешу или бесю