Разработка собственной библиотеки на Python: структура, сборка, публикация

Раздел: Python -> Разработка библиотек

Создание библиотеки Python

Как создать библиотеку с использованием pyproject.toml и setuptools (рекомендуемый способ)?

Современный стандарт предполагает использование файла pyproject.toml для описания метаданных и зависимостей. Это основной и наиболее эффективный подход, рекомендованный PEP 517/518 и сообществом Python.

Структура проекта


mypackage/
├── pyproject.toml
├── README.md
├── LICENSE
└── src/
    └── mypackage/
        ├── __init__.py
        └── core.py

создание библиотеки python (создание библиотеки python)

Каталог src/ используется по рекомендации для изоляции исходного кода от файлов конфигурации (такой подход называют «src layout»).

Содержимое pyproject.toml


[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.backends._legacy._Backend"

[project]
name = "mypackage"
version = "0.1.0"
description = "Пример библиотеки"
readme = "README.md"
authors = [
    {name = "Developer", email = "dev@example.com"}
]
license = {text = "MIT"}
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
]
dependencies = [
    "requests>=2.25",
]

[project.urls]
Homepage = "https://example.com"
Repository = "https://github.com/user/mypackage"

[tool.setuptools.packages.find]
where = ["src"]

Python написание библиотеки (создание собственной библиотеки python)

Поле dependencies указывает сторонние библиотеки, необходимые для работы вашей библиотеки. Поле classifiers помогает каталогизировать пакет на PyPI.

Код библиотеки (src/mypackage/core.py)


def greet(name: str) -> str:
    """Возвращает приветствие."""
    return f"Hello, {name}!"

написать библиотеку на python (создание библиотеки на python)

Установка в режиме разработки


pip install -e .

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

Типичные ошибки и их решения

Ошибка: ModuleNotFoundError при импорте

Причина: некорректно настроен путь поиска пакетов. В pyproject.toml нужно указать [tool.setuptools.packages.find] where = ["src"], если код находится в src/. Если src/ не используется, достаточно указать packages = ["mypackage"].

Ошибка: setuptools не устанавливает зависимости

Причина: устаревшая версия setuptools. Требуется обновление: pip install --upgrade setuptools.

Как создать библиотеку с помощью классического setup.py?

Этот вариант всё ещё встречается, но считается устаревшим. Вместо pyproject.toml используется файл setup.py с кодом на Python.

Структура


mypackage/
├── setup.py
├── setup.cfg (опционально)
├── README.md
├── LICENSE
└── mypackage/
    ├── __init__.py
    └── core.py

Пример setup.py


from setuptools import setup, find_packages

setup(
    name='mypackage',
    version='0.1.0',
    description='Пример библиотеки',
    author='Developer',
    author_email='dev@example.com',
    packages=find_packages(),
    install_requires=['requests>=2.25'],
    python_requires='>=3.8',
)

Функция find_packages() автоматически находит все подпакеты. Для установки в режиме разработки также используется pip install -e ..

Проблема: зависимости не устанавливаются

Причина: отсутствует аргумент install_requires или опечатка в именах пакетов. Проверьте правильность написания.

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

Poetry - современный инструмент, который объединяет в себе менеджер зависимостей, сборщик и публикатор. Он автоматически создаёт pyproject.toml и управляет виртуальным окружением.

Инициализация проекта


poetry new mypackage
cd mypackage

Команда создаёт структуру с папкой mypackage и файлами pyproject.toml, README.rst (можно заменить на .md).

Добавление зависимостей


poetry add requests

Poetry обновляет pyproject.toml и создаёт файл блокировки poetry.lock для точного воспроизведения окружения.

Установка и сборка


poetry install
poetry build

Команда build создаёт дистрибутивы (.tar.gz и .whl) в папке dist/.

Ошибка: конфликт версий зависимостей

Poetry строго следит за совместимостью. Если указать несовместимые версии, он выдаст ошибку. Рекомендуется использовать команду poetry lock --no-update для фиксации текущих версий.

Как создать библиотеку с помощью Flit для минималистичного подхода?

Flit - простой инструмент, который не требует отдельного файла setup.py. Метаданные берутся из модуля __init__.py или отдельного файла __version__.py.

Настройка pyproject.toml для Flit


[build-system]
requires = ["flit_core>=3.2"]
build-backend = "flit_core.buildapi"

[project]
name = "mypackage"
authors = [{name = "Developer", email = "dev@example.com"}]
readme = "README.md"
classifiers = ["Programming Language :: Python :: 3"]
dependencies = []

Установка


pip install flit
flit install

Flit также поддерживает публикацию одной командой flit publish.

Проблема: Flit не находит версию

По умолчанию Flit ищет атрибут __version__ в самом верхнем модуле пакета (__init__.py). Необходимо определить эту переменную, например: __version__ = "0.1.0".

Все описанные варианты позволяют создать библиотеку, но основное эффективное решение - использование pyproject.toml с setuptools или Poetry, так как они следуют современным стандартам и широко поддерживаются.

Расширенные примеры создания библиотеки Python

1. Библиотека с расширениями на Cython

Допустим, требуется ускорение критического участка кода с помощью Cython. Создадим файл src/mypackage/calc.pyx:

Пример

def fast_sum(int a, int b):
    cdef int c = a + b
    return c

Настроим pyproject.toml с использованием setuptools и Cython:

Пример

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

[project]
name = "mypackage-ext"
version = "0.1.0"

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools.ext-modules]
mypackage.calc = "src/mypackage/calc.pyx"

Сборка выполняется командой pip install -e . - Cython скомпилирует .pyx в машинный код.

Результат (пример вызова):

>>> from mypackage.calc import fast_sum
>>> fast_sum(100, 200)
300

2. Библиотека с точками входа (entry points)

Создадим консольный скрипт, который будет устанавливаться вместе с библиотекой. Для этого в pyproject.toml добавляем секцию [project.scripts]:

Пример

[project.scripts]
greet = "mypackage.cli:main"

Соответствующий модуль src/mypackage/cli.py:

Пример

def main():
    print("Hello from mypackage!")

После установки (pip install -e .) в терминале можно запустить:

$ greet
Hello from mypackage!

3. Публикация пакета на Test PyPI и PyPI

Для тестовой публикации используем TestPyPI. Предварительно необходимо зарегистрироваться на https://test.pypi.org и получить API-токен.

Сборка дистрибутивов:

Пример

python -m build

Установка twine и загрузка на TestPyPI:

Пример

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

После этого библиотеку можно установить с TestPyPI:

Пример

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

Для публикации на основной PyPI команда упрощается:

Пример

twine upload dist/*

Результат: пакет становится доступен для установки через pip install mypackage.

4. Версионирование с помощью setuptools_scm

Автоматическое определение версии на основе git-тегов. Добавляем в pyproject.toml:

Пример

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

[project]
name = "mypackage"
dynamic = ["version"]

[tool.setuptools_scm]

Теперь версия будет браться из последнего git-тега. Например, при теге v0.2.0 версия пакета будет 0.2.0. Если коммит не отмечен тегом, setuptools_scm генерирует версию, содержащую количество коммитов с последнего тега и хэш (например, 0.2.0.dev5+gabcdef1).

Пример вывода при импорте:

>>> import mypackage
>>> mypackage.__version__
'0.2.0'

5. Включение не-Python файлов (data files)

Если в библиотеку нужно включить, например, JSON-конфиги или изображения, используем [tool.setuptools.package-data]:

Пример

[tool.setuptools.package-data]
"*" = ["*.json", "*.png"]

Или в setup.py (если используется) аргумент package_data={'' : ['*.json']}.

Файлы будут скопированы в соответствующую папку дистрибутива, и их можно получить через importlib.resources (Python 3.9+) или pkg_resources.

Создание библиотеки Python - comments

En
создание библиотеки python (python)