Создание библиотеки Python с примерами

Как создать библиотеку python примеры

Как создать библиотеку python примеры

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

Для начала стоит определить назначение будущей библиотеки: узкоспециализированный модуль для внутреннего проекта или универсальное решение, которое можно опубликовать на PyPI. В первом случае достаточно локальной структуры с каталогом и файлом __init__.py, во втором – потребуется добавить pyproject.toml или setup.cfg для описания метаданных и зависимостей.

Важным этапом является организация структуры кода. Рекомендуется придерживаться схемы: отдельная папка с исходниками, каталог tests для автоматизированных проверок и документация в формате README.md. Такая структура делает проект понятным для других разработчиков и совместимым с системами непрерывной интеграции.

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

Выбор структуры проекта и организация каталогов

Выбор структуры проекта и организация каталогов

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

Элемент Назначение
project_name/ Основная директория исходного кода библиотеки
project_name/__init__.py Определяет пакет, хранит метаданные (версия, автор)
tests/ Модульные тесты, разделённые по модулям
pyproject.toml Описание зависимостей и настроек сборки (PEP 621)
README.md Документация для пользователей и PyPI
LICENSE Условия распространения кода

Для изоляции служебного кода рекомендуется размещать внутренние модули в подпапке _internal, а публичные API – в корневом уровне пакета. Если библиотека предоставляет CLI, директорию cli/ следует отделить от основной логики.

Пример рекомендуемой структуры:

project_name/
├── project_name/
│   ├── __init__.py
│   ├── core.py
│   ├── utils.py
│   └── _internal/
│       └── helpers.py
├── cli/
│   └── main.py
├── tests/
│   ├── test_core.py
│   └── test_utils.py
├── pyproject.toml
├── README.md
└── LICENSE

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

Создание файла setup.py и настройка зависимостей

Файл setup.py определяет метаданные пакета и список зависимостей. Он должен находиться в корне проекта рядом с каталогом библиотеки.

Минимальная структура:

from setuptools import setup, find_packages
setup(
name="mypackage",
version="0.1.0",
packages=find_packages(),
install_requires=[
"requests>=2.31.0",
"numpy>=1.26.0,<2.0.0"
],
python_requires=">=3.9",
)

Ключевые параметры:

  • name – уникальное имя пакета на PyPI.
  • version – следует использовать семантическое версионирование (MAJOR.MINOR.PATCH).
  • packages – автоматически определяется с помощью find_packages(), исключая ненужные каталоги (tests, docs).
  • install_requires – список зависимостей с указанием диапазонов версий для предотвращения конфликтов.
  • python_requires – ограничение поддерживаемых версий Python.

Рекомендации по зависимостям:

  1. Указывать минимально необходимую версию, например requests>=2.31.0, чтобы избежать несовместимости со старыми релизами.
  2. Фиксировать верхнюю границу для крупных библиотек (numpy>=1.26.0,<2.0.0), так как мажорные версии могут ломать обратную совместимость.
  3. Выносить инструменты разработки (pytest, black) в отдельный файл requirements-dev.txt или секцию extras_require.

Пример с дополнительными зависимостями:

setup(
...
extras_require={
"dev": ["pytest>=7.4.0", "black>=23.9.0"],
"docs": ["sphinx>=7.2.0"]
}
)

После создания файла пакет можно установить локально:

pip install -e .

Добавление и документирование функций внутри пакета

Функции в пакете размещаются в отдельных модулях, сгруппированных по назначению. Например, математические операции логично хранить в файле math_utils.py, а обработку строк – в string_utils.py. Такое разделение упрощает поддержку и тестирование.

Каждая функция должна сопровождаться докстрингом в формате PEP 257 и описывать назначение, аргументы и возвращаемое значение. Для большей читаемости применяют стиль reStructuredText или Google Style. Пример:

def normalize_vector(v: list[float]) -> list[float]:
"""
Нормализация вектора до единичной длины.
Args:
v (list[float]): входной вектор.
Returns:
list[float]: нормализованный вектор.
"""
length = sum(x2 for x in v)  0.5
return [x / length for x in v]

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

# __init__.py
from .math_utils import normalize_vector
__all__ = ["normalize_vector"]

Документирование функций напрямую влияет на автогенерацию документации инструментами Sphinx или pdoc. Наличие чётких докстрингов позволяет без дополнительной правки формировать полноценный справочник по API.

Использование __init__.py для управления импортами

Файл __init__.py определяет интерфейс пакета и управляет тем, какие объекты доступны при импорте. Если оставить его пустым, Python будет воспринимать каталог как пакет, но без дополнительной логики. Однако грамотное наполнение файла позволяет скрывать внутренние модули и упрощать доступ к нужным функциям.

Часто в __init__.py размещают список __all__, чтобы ограничить экспортируемые объекты. Например:

from .core import calculate
from .utils import format_output
all = ["calculate", "format_output"]

Теперь при использовании from package import * будут доступны только указанные имена. Это помогает избежать утечки лишних функций и конфликтов имен.

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

# вместо package.core.calculate
# достаточно package.calculate
from .core import calculate
from .models import DataModel

Такой подход особенно полезен при создании стабильного публичного API: внутренние файлы можно свободно изменять без риска сломать код пользователей. Важно документировать, какие объекты импортируются в __init__.py, чтобы избежать путаницы.

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

Написание и запуск модульных тестов

Написание и запуск модульных тестов

Для проверки корректности библиотеки используйте стандартный модуль unittest. Каждый тест оформляется в виде метода внутри класса, наследующего unittest.TestCase. Названия методов начинайте с test_, чтобы они автоматически определялись как тесты.

Пример структуры файла test_utils.py:

import unittest
from mylib.utils import add_numbers
class TestUtils(unittest.TestCase):
def test_add_numbers_positive(self):
self.assertEqual(add_numbers(2, 3), 5)
rubyCopy codedef test_add_numbers_negative(self):
self.assertEqual(add_numbers(-1, -4), -5)
if name == "main":
unittest.main()

Запуск возможен напрямую: python -m unittest test_utils.py. Для запуска всех тестов в каталоге используйте: python -m unittest discover -s tests.

Рекомендуется хранить тесты в отдельной папке tests с аналогичной структурой модулей. Это упрощает навигацию и интеграцию с CI/CD.

При разработке расширенной библиотеки стоит подключить pytest, так как он поддерживает параметризацию и более лаконичный синтаксис:

import pytest
from mylib.utils import add_numbers
@pytest.mark.parametrize("a,b,result", [(2,3,5), (-1,-4,-5)])
def test_add_numbers(a, b, result):
assert add_numbers(a, b) == result

Запуск всех тестов в этом случае: pytest.

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

Сборка пакета и подготовка к публикации

Сборка пакета и подготовка к публикации

Создайте pyproject.toml для указания сборщика. Пример с setuptools:

[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"

Выполните сборку дистрибутива командой:

python -m build

В каталоге dist/ появятся .tar.gz и .whl файлы для публикации.

Проверка метаданных:

twine check dist/*

Для публикации на PyPI используйте:

twine upload dist/*

Тестовую загрузку выполняйте через TestPyPI:

twine upload --repository testpypi dist/*

Укажите корректное описание в README.md и подключите его в сборке:

long_description = file: README.md
long_description_content_type = text/markdown

Фиксируйте версии зависимостей в setup.cfg или pyproject.toml для совместимости:

install_requires = ["requests==2.31.0", "numpy>=1.26,<2.0"]

Проверка установки в чистом окружении:

python -m venv venv_test && source venv_test/bin/activate && pip install your-package

Загрузка библиотеки на PyPI с помощью twine

Загрузка библиотеки на PyPI с помощью twine

Убедитесь, что установлены актуальные версии пакетов setuptools, wheel и twine:

python -m pip install --upgrade setuptools wheel twine

Соберите исходный дистрибутив и wheel-файл:

python setup.py sdist bdist_wheel

В папке dist/ появятся файлы:

  • имя_пакета-версия.tar.gz – исходный код
  • имя_пакета-версия-py3-none-any.whl – wheel-пакет

Для тестовой публикации используйте Test PyPI:

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

Проверьте установку пакета из Test PyPI:

pip install --index-url https://test.pypi.org/simple/ имя_пакета

Для загрузки на основной PyPI выполните:

twine upload dist/*

Для хранения учетных данных создайте файл ~/.pypirc с содержимым:

[pypi]
username = ваш_логин
password = ваш_пароль

Для обновления версии пакета:

  1. Измените version в setup.py или pyproject.toml.
  2. Пересоберите дистрибутивы командой python setup.py sdist bdist_wheel.
  3. Загрузите новую версию через twine upload dist/*.

Использование twine обеспечивает безопасную аутентификацию и корректную загрузку пакетов без прямого ввода логина и пароля в командной строке.

Вопрос-ответ:

Как правильно организовать структуру файлов в библиотеке Python?

Структура файлов влияет на удобство использования и поддержку библиотеки. Обычно создают папку с названием библиотеки, внутри которой располагают основной код в отдельной папке, файл setup.py для установки, README.md с описанием и LICENSE. Для модулей лучше использовать отдельные файлы с осмысленными именами, а тесты — в отдельной папке tests. Такая организация помогает другим разработчикам быстро ориентироваться и подключать нужные модули.

Какие инструменты можно использовать для тестирования функций библиотеки?

Для проверки работы функций подходят стандартные средства Python, например, модуль unittest, который позволяет создавать наборы тестов для различных функций. Также популярны библиотеки pytest и doctest. Pytest удобен тем, что позволяет писать тесты коротко и ясно, а doctest дает возможность проверять примеры прямо из документации. Выбор зависит от того, какой подход ближе: формальный набор тестов или проверка на примерах из документации.

Как добавить документацию к функциям библиотеки?

Документацию удобно размещать прямо в коде с помощью строк документации (docstrings). Они записываются в тройных кавычках сразу после определения функции или класса. В docstring обычно указывают назначение функции, описание аргументов и возвращаемого значения, а также пример использования. Такой подход позволяет автоматически генерировать документацию с помощью инструментов вроде Sphinx или pdoc.

Какие шаги нужны для публикации библиотеки на PyPI?

Для публикации создают учетную запись на сайте PyPI, затем готовят пакет с setup.py или pyproject.toml, включая информацию о версии, авторе и зависимостях. После этого с помощью инструментов twine и setuptools библиотеку загружают на PyPI. Перед публикацией полезно проверить пакет локально, используя команду pip install . из корневой папки проекта. Это помогает убедиться, что все файлы включены и установка проходит корректно.

Как правильно продемонстрировать работу библиотеки через примеры?

Примеры работы лучше размещать в README.md и в отдельных файлах примеров. Они должны быть понятными и показывать основные функции библиотеки, включая обработку типичных ситуаций и возможные ошибки. Хороший пример начинается с импорта функций, демонстрирует их использование с разными параметрами и показывает ожидаемый результат. Это помогает новым пользователям быстрее освоить библиотеку и понять, как применять её функции в своих проектах.

Как правильно структурировать файлы при создании собственной библиотеки Python?

При разработке библиотеки важно продумать структуру каталогов. Обычно создают корневую папку с названием проекта, внутри которой размещают папку с основным кодом библиотеки, например, с тем же именем. Внутри этой папки располагают модули — отдельные Python-файлы, отвечающие за конкретные функции или классы. Помимо этого создают файл setup.py для установки библиотеки, README.md с описанием проекта и папку tests для тестирования кода. Такая организация облегчает поддержку и распространение библиотеки, а также помогает другим разработчикам быстро понять, как использовать её функции.

Ссылка на основную публикацию