Привет друзья!

Это моя первая статья на Хабр'е и в ней я вам расскажу о том, как создать свою библиотеку Python и загрузить её на PyPi. Давайте начнём.


Капельку определений

PyPI — каталог программного обеспечения, написанного на языке программирования Python. Фактически это хранилище открытых библиотек для языка Python. Каждый может скачать и использовать библиотеку или создать и загрузить свою. По состоянию на февраль 2020 года содержит более 216 000 пакетов.

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

Для чего вам нужна своя библиотека?

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

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

  • В-третьих, это весело и интересно.

Что вам нужно для создания библиотеки?

  • Код с функциями, которые вы планируете использовать.

  • Набор пакетов для создания и публикации (setuptools, wheel и twine).

  • Аккаунт PyPI (и его API токен - опционально, но об этом позже).

  • Желание и терпение.


Подготовка

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

Для начала, после того как у вас появилась идея, реализуйте всё в отдельном файле и уже потом разбейте на соответствующую структуру (об этом позже). Для примера я буду использовать код класса быстрого взаимодействия с файлами и библиотеку PyDeepLib (возможно позже я напишу об этом статью). Вы можете установить каждую из библиотек командами pip install PyDeepLib и pip install speedfile соответственно. Проекты так же доступны на GitHub (PyDeepLib, speedfile).

Итак, давайте начнём с установки необходимых нам библиотек. Откройте PyCharm (я рекомендую вам использовать именно его, но если у вас его нет, то можете использовать любой другой редактор кода). Создайте новый проект с виртуальным окружением и установите пакеты о которых говорилось раньше (setuptools, wheel и twine), используя команду pip install setuptools wheel twine.

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


Файлы нашего проекта на этом этапе должны выглядеть вот так:

Файлы проекта
Файлы проекта

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

Регистрация на PyPi

Я не очень хочу подробно на этом останавливаться, но я это сделаю:

Для регистрации на PyPi вам нежно перейти на сайт pypi.org и нажать на кнопку зарегистрироваться:

pypi.org
pypi.org

После этого все стандартно:

Имя, почта, username и пароль. Я думаю вы с этим справитесь.

Файлы setup.py и setup.cfg

Теперь займёмся кодом, который будет устанавливать нашу библиотеку. Для начала откройте файл setup.py. Теперь напишем в него такой код:

from setuptools import setup, find_packages


def readme():
  with open('README.md', 'r') as f:
    return f.read()


setup(
  name='speedfile',
  version='0.0.1',
  author='yarik_g',
  author_email='example@gmail.com',
  description='This is the simplest module for quick work with files.',
  long_description=readme(),
  long_description_content_type='text/markdown',
  url='your_url',
  packages=find_packages(),
  install_requires=['requests>=2.25.1'],
  classifiers=[
    'Programming Language :: Python :: 3.11',
    'License :: OSI Approved :: MIT License',
    'Operating System :: OS Independent'
  ],
  keywords='files speedfiles ',
  project_urls={
    'GitHub': 'your_github'
  },
  python_requires='>=3.6'
)

Итак, сначала мы создаём функцию readme , она нужна для чтения README.md файла (я расскажу как создать его максимально быстро и просто позже). И затем мы вызываем функцию setup, в которую нам надо передать некоторое число параметров, о них поговорим подробнее:

  • name - название вашей библиотеки.

  • version - версия. Когда будете обновлять библиотеку, версию обязательно надо изменить.

  • author - автор проекта

  • author_email - электронная почта (желательно та, на которую регистрировали аккаунт на PyPi).

  • description - короткое описание.

  • long_description - подробное описание пакета. В данном случае получение содержимого файла README.md.

  • long_description_content_type - разметка, используемая в подробном описании. У нас - markdown.

  • url - ссылка на страницу пакета. Я там указал ссылку на GitHub проекта.

  • packages - список пакетов, которые должны опубликоваться. Для удобства я использовал функцию find_packages.

  • install_requires - дополнительные библиотеки, которые будут установлены вместе с пакетом.

  • classifiers - метаданные о пакете.

  • keywords - ключевые слова (через пробел).

  • project_urls - дополнительные ссылки пакета.

  • python_requires - требуемая версия Python.

Отлично, надеюсь, что с этом мы разобрались. Теперь надо отредактировать файл setup.cfg. Если коротеничко, открываем его и вставляем это:

[egg_info]
tag_build =
tag_date = 0

В нашем случае проект очень простой и не требует никакой дополнительной конфигурации.

Основные файлы

Итак, давайте снова вернёмся к файлам проекта PyDeepLib, и рассмотрим устройство файлов модуля.

Ещё раз файлы проекта...
Ещё раз файлы проекта...

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

Пример файла инициализации проекта
Пример файла инициализации проекта

Как видите в нём почти нет кода, только import'ы, весь остальной код же разбит по отдельным файлам. Это намного удобнее чем держать весь код в одном файле, однако к примеру в проекте speedfile весь код располагался в этом основном файле, но там он был небольшим и запутаться там было сложно:

Фрагмент файла инициализации из speedfile
Фрагмент файла инициализации из speedfile

Я думаю, что это всё что надо знать про разбиение кода на модули.

Создание README файла. Красиво и быстро.

У каждой библиотеки должна быть своя документация или хотя-бы описание. Обычно для этого используют README.md файлы. Логично предположить, что для полноты картины нам тоже следует сделать такой файл для библиотеки. Для создания .md файла мы будем использовать редактор markdown файлов, с говорящим названием MarkDownPad2.

Итак, для начало надо скачать редактор (при желании этот пункт можно пропустить. Вы можете редактировать .md файлы прямо в PyCharm или в любом текстовом редакторе, сохранив файл с соответствующим расширением).

Переходим на сайт markdownpad.com и видим, что существует две версии этого редактора, markdownpad free и markdownpad pro. Для наших задач нам вполне хватит бесплатной версии, поэтому жмём на кнопку скачать:

markdownpad.com

После этого начнётся загрузка и потом останется только установить редактор. Я думаю что вы с этим справитесь, но если что, то на сайте есть инструкция:

Установка MDPad
Установка MDPad

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

Фактически, типичное окно редактора текста/кода, каковым MarkDownPad фактически и является. Дальше принцип простой: просто пишем в файл всё то, что вам необходимо иметь в README файле для вашего проекта и применяете инструменты форматирования, такие как: код, цитата, ссылка, заголовок, список и т.д. Я думаю, что самостоятельно разобраться с markdown разметкой будет не очень сложно, но если что, то вот вам полезная статья с наглядным руководством по markdown.

Для примера я просто дам вам код README.md файла библиотеки speedfile:

# Speed File Library #

## What is this? ##
The module allows you to work with files in just one line of code, without the need to manually open and close the file each time

## Quick Guide ##
The module is based on the following structure:

    
    f = open('data.txt')
    data = f.readlines()
    f.close()
    
Which Python provides by standard.


----------


### Using ###


Using the library is as simple and convenient as possible:

Let's import it first:
First, import everything from the library (use the `from `...` import *` construct).

Examples of all operations:

Writing the contents of an entire file to a variable using the `read()` function:

    temp = File(path='test.txt').read()


Writing the contents of an entire file to a variable line by line using the `readlines()` function:

    temp = File(path='test.txt').readlines()


Write only the first line from a file using the `readline()` function:

    temp = File(path='test.txt').readline()


Writing data from a variable to a file using write() (overwriting or creating a file):

    temp = "Test data"
    File(path='test.txt', data=temp).write()
    

Adding data from a variable to a file using write() (or creating a file):

    temp = "Test data"
    File(path='test.txt', data=temp).add()


----------


## Developer ##
My site: [link](https://y-a-r-i-k.github.io/) 

И то, как он выглядит на GitHub:

Speedfile на GitHub
Speedfile на GitHub

Я надеюсь, вы здесь разберётесь)).

Публикация пакета

Ок, если вы выполнили все предшествующие шаги, но вы готовы к публикации пакета. Итак, переходим к делу:

Открываем терминал или используем встроенный в PyCharm (или редактор кода, который вы используете). Переходим в корневую директорию проекта и пишем:

python setup.py sdist bdist_wheel

После этого создадутся несколько новых папок. Теперь мы готовы к собственно загрузке модуля на PyPi. Пишем это в терминал:

twine upload --repository pypi dist/*

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

Как же это решить? Очень просто. Вам нужно получить ваш API токен для PyPi.

  1. Переходим в настройки учётной записи:

  1. Крутим вниз до пункта с API-токенами и жмём добавить токен:

  1. Далее вас попросят назвать токен и выбрать область его действия:

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

Итак, обратно выгрузке проекта: теперь в поле для ввода username вам надо указать __token__ а туда где должен быть пароль - ваш API-токен (рекомендую использовать пункт paste или вставить из контекстного меню, так так Ctrl + V может сработать не корректно). После этого жмём Enter и ждём. После завершения загрузки вам дадут ссылку на страницу с вашей библиотекой.

Страница будет выглядеть стандартно, например вот страница PyDeepLib:

PyDeepLib
PyDeepLib

Ну, и на этом всё, поздравляю! Вы создали и загрузили свою первую библиотеку на PyPi.

От автора:

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

Ещё раз спасибо, что дочитали до сюда!

Удачи!

Комментарии (11)


  1. Andrey_Solomatin
    10.09.2023 15:29
    -4

    Не дочитал до конца.

    Без упоминания poetry и flit этот тьюториал выглядит неполным.


    1. YarIkGU Автор
      10.09.2023 15:29
      +1

      Я писал только про то, чем пользуюсь сам и с чем умею работать. Если хотите помочь в доработке этой статьи, то можете написать мне в ТГ. Все ссылки в конце статьи. Спасибо.


      1. Andrey_Solomatin
        10.09.2023 15:29
        +2

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


  1. berng
    10.09.2023 15:29

    Заработало. Только вместо

    from mylib import myclass

    приходится писать

    from mylib.myclass import myclass

    Не подскажете, как сделать класс дефолтным?


    1. me21
      10.09.2023 15:29
      +1

      Могу ошибиться, но попробуйте в __init__.py библиотеки его импортировать. Тогда для внешнего кода импорт должен заработать так, как вы написали.


    1. YarIkGU Автор
      10.09.2023 15:29

      Я также как и@me21не уверен в чём проблема именно у вас, но вероятно вы действительно не прописали соответствующий импорты в __init__.py. Для примера этот файл в библиотеке PyDeepLib выглядит так:

      from .tensorclass import *
      from .layers import *
      from .speedfilein import *
      from .loggingin import *

      Вы можете сами в этом убедиться: GitHub.


  1. cartonworld
    10.09.2023 15:29
    +1

    Вместо markdownPad проще использовать Markdown Support | PyCharm


    1. YarIkGU Автор
      10.09.2023 15:29

      Спасибо. Это действительно так, но для пользователей не очень знакомых с синтаксисом markdown MDPad будет проще.


  1. Alesh
    10.09.2023 15:29
    +2

    Способ с setup.py уже устарел. Для статьи стоило бы разобрать современные методы.


  1. milssky
    10.09.2023 15:29
    +6

    Устаревший способ. Авторы языка предлагают использовать pyproject.toml. Современная инструкция со всеми примерами в документации. https://packaging.python.org/en/latest/tutorials/packaging-projects/


  1. enkryptor
    10.09.2023 15:29

    Спасибо, что дочитали статью до конца, надуюсь

    Автор, не обижайтесь! Однако ж, описанный алгоритм выглядит без нужды усложнённым. Качать и устанавливать конкретную отдельную программу для редактирования README? Маркдаун — это обычный текст, так же как и py-файлы. Если читатель написал код и дошёл до публикации библиотеки в PyPi, редактировать текстовые файлы он уже умеет.