Разработка собственной библиотеки на 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.