Пользовательские библиотеки: разработка и публикация пакетов
Создание пользовательских библиотек в Python
Как создать библиотеку с возможностью установки через pip install?
Современный способ создания библиотеки предполагает использование файла pyproject.toml в корне проекта. Этот подход рекомендован PEP 518 и поддерживается большинством инструментов сборки, такими как setuptools, poetry, flit. Рассмотрим минимальную структуру:
mylib/
├── mylib/
│ ├── __init__.py
│ └── core.py
├── pyproject.toml
└── README.mdPython библиотеки словари (библиотеки для работы со словарями в python)
Файл pyproject.toml содержит метаданные и настройки сборки. Пример:
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "mylib"
version = "0.1.0"
description = "Пример пользовательской библиотеки"
authors = [{name = "Ваше Имя", email = "email@example.com"}]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.8"библиотека python user (пользовательские библиотеки python)
После сохранения файлов в корне проекта выполняется установка в режиме разработки:
pip install -e .
библиотека алгоритмов python (библиотека алгоритмов в python)
Теперь библиотеку можно импортировать из любого скрипта:
from mylib.core import some_function
print(some_function())библиотека скриптов python (библиотека скриптов в python)
Типичные проблемы:
- ModuleNotFoundError: если забыли поместить
__init__.pyв папку пакета. Решение: добавить пустой файл. - Ошибка версии: если указан
requires-pythonслишком высокий. Решение: снизить требование. - Конфликт с системными пакетами: использование виртуального окружения решает эту проблему.
Как использовать один скрипт как библиотеку?
Если код состоит из одного файла, достаточно поместить его в тот же каталог, что и основной скрипт, или добавить путь в sys.path. Пример: файл utils.py с функцией add(a,b). Импорт: from utils import add. Для многократного использования удобнее превратить его в модуль с установкой.
Проблема:
При перемещении файла импорт ломается. Решение: оформить как пакет с установкой.
Как организовать код в пакет без установки?
Просто создается папка с файлом __init__.py и помещается в PYTHONPATH или в ту же директорию, что и вызывающий скрипт. Пример: mypackage/__init__.py и mypackage/module.py. Импорт: from mypackage import module. Однако такой способ не позволяет управлять зависимостями и версиями.
Как создать библиотеку с помощью setup.py (старый способ)?
Вместо pyproject.toml можно использовать setup.py:
from setuptools import setup, find_packages
setup(
name='mylib',
version='0.1',
packages=find_packages(),
install_requires=[],
)библиотеки работы с файлами python (библиотеки для работы с файлами в python)
Установка: pip install -e . или python setup.py develop. Этот метод устарел, но все еще работает.
Ошибка:
При использовании python setup.py install могут возникнуть проблемы с разрешением зависимостей. Рекомендуется pip install .
Как тестировать библиотеку в процессе разработки?
Режим разработки (pip install -e .) создает ссылку на исходный код, поэтому изменения вступают в силу сразу без переустановки. Это удобно для отладки.
pip install -e .Python библиотека сети (сетевая библиотека в python)
Как распространять библиотеку в виде собранного колеса?
Сборка wheel выполняется командой:
python -m buildВ результате появляется архив dist/mylib-0.1.0-py3-none-any.whl. Установка:
pip install dist/mylib-0.1.0-py3-none-any.whlПроблема:
Если wheel не содержит нужных файлов, проверяется MANIFEST.in или include_package_data=True.
Как опубликовать библиотеку в открытом репозитории PyPI?
После тестирования и сборки wheel используется twine:
pip install twine
twine upload dist/*Потребуется учетная запись на PyPI. После публикации библиотека становится доступна для установки через pip install mylib.
Ошибка 403:
Имя пакета уже занято. Необходимо выбрать уникальное имя.
Расширенные примеры работы с пользовательскими библиотеками
Пример 1: Пакет с вложенными подпакетами и модулями
Структура:
mypackage/
├── mypackage/
│ ├── __init__.py
│ ├── subpackage/
│ │ ├── __init__.py
│ │ └── helper.py
│ └── utils.py
├── pyproject.toml
└── README.mdВ mypackage/__init__.py импортируются элементы public API:
from .utils import add
from .subpackage.helper import greetТеперь пользователь может писать:
import mypackage
print(mypackage.add(2,3))
print(mypackage.greet("Мир"))Результат:
5
Привет, Мир!
Пример 2: Использование __all__ для контроля экспорта
В модуле utils.py:
__all__ = ['add', 'subtract']
def add(a,b): return a+b
def subtract(a,b): return a-b
def _private(): return "скрыто"При импорте from mypackage.utils import * будут доступны только add и subtract. Это защищает внутреннюю реализацию.
Пример 3: Добавление зависимостей и версионирование
В pyproject.toml:
[project]
dependencies = [
"numpy>=1.21",
"requests"
]
[tool.setuptools.dynamic]
version = {attr = "mypackage.__version__"}В mypackage/__init__.py прописывается:
__version__ = "0.2.0"Теперь версия автоматически берется из кода, а зависимости устанавливаются при установке пакета.
Пример 4: Создание entry points (консольных скриптов)
Добавление в pyproject.toml:
[project.scripts]
my-cli = "mypackage.cli:main"Создается mypackage/cli.py:
def main():
print("Консольная команда my-cli запущена")После установки пакета команда my-cli становится доступна в терминале.
$ my-cli
Консольная команда my-cli запущена
Пример 5: Комплексная публикация с использованием Makefile и twine
Создается файл Makefile:
.PHONY: build upload
build:
python -m build
upload:
twine upload dist/*Затем команды:
make build
make uploadЭто автоматизирует процесс сборки и публикации. Перед загрузкой рекомендуется тестирование на TestPyPI:
pip install twine
twine upload --repository testpypi dist/*
pip install --index-url https://test.pypi.org/simple/ mylibОшибка: конфликт зависимостей при установке
Если библиотека требует numpy определенной версии, у пользователя может стоять другая. Решение: указывать минимальную версию без строгих ограничений (например, numpy>=1.21) или использовать pip для разрешения конфликтов.