← Назад к вопросам

Как работает пакетирование библиотек?

2.2 Middle🔥 101 комментариев
#DevOps и инфраструктура#Python Core

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Пакетирование библиотек в Python: полное руководство

Пакетирование (packaging) — это процесс подготовки Python кода для распространения и установки. За 10+ лет я видел эволюцию этого процесса от distutils к современным инструментам, и это критический навык для любого профессионального разработчика.

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

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

my_library/
├── src/
│   └── my_library/
│       ├── __init__.py
│       ├── core.py
│       └── utils.py
├── tests/
│   ├── test_core.py
│   └── test_utils.py
├── docs/
│   └── README.md
├── pyproject.toml
├── setup.py  (опционально для обратной совместимости)
├── setup.cfg
├── LICENSE
└── README.md

Шаг 1: Конфигурация через pyproject.toml

Современный стандарт — использовать pyproject.toml (PEP 517, 518, 621):

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

[project]
name = "my-library"
version = "0.1.0"
description = "A brief description"
authors = [{name = "Your Name", email = "you@example.com"}]
license = {text = "MIT"}
requires-python = ">=3.8"
dependencies = [
    "requests>=2.28.0",
    "pydantic>=2.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "black>=23.0",
    "ruff>=0.1.0",
]
docs = [
    "sphinx>=5.0",
    "sphinx-rtd-theme>=1.0",
]

[project.urls]
Homepage = "https://github.com/yourname/my-library"
Documentation = "https://my-library.readthedocs.io"
Repository = "https://github.com/yourname/my-library"

[tool.setuptools]
package-dir = {"" = "src"}

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

Шаг 2: Создание дистрибутивов

SETUPTOOLS генерирует два типа пакетов:

Source Distribution (sdist) — исходный код:

python -m build --sdist
# Результат: dist/my-library-0.1.0.tar.gz
# Содержит: весь исходный код, тесты, документация

Wheel (bdist) — готовый к установке:

python -m build --wheel
# Результат: dist/my_library-0.1.0-py3-none-any.whl
# Содержит: скомпилированный код, метаданные, готов к установке

Полная сборка (оба типа):

python -m build
# Создаёт оба: .tar.gz и .whl

Шаг 3: Метаданные пакета

Внутри каждого пакета находится папка *.dist-info с метаданными:

my_library-0.1.0.dist-info/
├── METADATA          # Информация о пакете (имя, версия, зависимости)
├── WHEEL             # Информация о wheel
├── entry_points.txt  # CLI команды пакета
├── top_level.txt     # Основные модули
└── RECORD            # Список всех файлов с хешами

Пример METADATA:

Metadata-Version: 2.1
Name: my-library
Version: 0.1.0
Summary: A brief description
Author: Your Name
Author-email: you@example.com
Home-page: https://github.com/yourname/my-library
Requires-Python: >=3.8
Requires-Dist: requests (>=2.28.0)
Requires-Dist: pydantic (>=2.0)

Шаг 4: Загрузка на PyPI

# Установить twine для загрузки
pip install twine

# Загрузить на PyPI (требует аккаунта)
twine upload dist/*

# Или на тестовый PyPI для проверки
twine upload --repository testpypi dist/*

Шаг 5: Установка пакета

После загрузки пользователи могут установить:

pip install my-library
# pip находит пакет на PyPI, скачивает wheel, распаковывает

Механизм установки (как pip работает)

# 1. Разрешение зависимостей (dependency resolution)
# pip читает METADATA и рекурсивно разрешает зависимости

# 2. Скачивание
# pip скачивает .whl (или .tar.gz, затем собирает wheel)

# 3. Распаковка и установка
# Распаковывает в site-packages/
# my_library/
# my_library-0.1.0.dist-info/

# 4. Обновление PATH
# Если есть скрипты (entry_points) — создаёт CLI команды

Entry Points: создание CLI команд

[project.scripts]
my-app = "my_library.cli:main"

[project.gui-scripts]
my-gui = "my_library.gui:launch"

Тогда после установки доступна команда:

$ my-app --help  # Вызывает функцию main() из my_library.cli

Реализация:

# my_library/cli.py
def main():
    print("Hello from CLI!")

if __name__ == "__main__":
    main()

Управление версиями

Семантическое версионирование (SemVer):

MAJOR.MINOR.PATCH
0.1.5
│ │ └─ Патч (исправления багов, не меняет API)
│ └──── Минор (новые фичи, обратно совместимо)
└────── Мажор (ломающие изменения)

Автоматизация версий с setuptools_scm:

[tool.setuptools_scm]
# Версия определяется из git tags автоматически
# git tag v0.2.0
# версия = 0.2.0

Развитие пакета (editable install)

Для разработки:

pip install -e .[dev]
# Устанавливает пакет в режиме редактирования
# Изменения в src/ видны сразу без переустановки

Файл setup.py для старых систем

Хотя современный стандарт — pyproject.toml, иногда нужен setup.py для совместимости:

from setuptools import setup, find_packages

setup(
    name="my-library",
    version="0.1.0",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    python_requires=">=3.8",
    install_requires=[
        "requests>=2.28.0",
        "pydantic>=2.0",
    ],
)

Полный workflow примера

# 1. Создание проекта
mkdir my-library && cd my-library
mkdir -p src/my_library tests

# 2. Написание кода и тестов
echo 'def hello(): return "Hello!"' > src/my_library/core.py

# 3. Создание pyproject.toml (как выше)

# 4. Локальная разработка
pip install -e .[dev]
pytest  # Запуск тестов

# 5. Сборка пакета
pip install build
python -m build
ls dist/  # Получим .tar.gz и .whl

# 6. Проверка на test PyPI
twine upload --repository testpypi dist/*

# 7. Финальная загрузка на PyPI
twine upload dist/*

Инструменты экосистемы

ИнструментНазначение
buildУниверсальная сборка
setuptoolsОсновной инструмент для сборки
wheelФормат и инструмент для wheel
twineБезопасная загрузка на PyPI
setuptools_scmВерсионирование из git
flitУпрощённая альтернатива setuptools
poetryAll-in-one: dependency management + packaging

Итого: как работает пакетирование

  1. Структурируем код (src layout)
  2. Определяем метаданные (pyproject.toml)
  3. Собираем дистрибутивы (sdist + wheel)
  4. Загружаем на PyPI (twine)
  5. Пользователи устанавливают (pip install)
  6. Pip распаковывает в site-packages

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

Как работает пакетирование библиотек? | PrepBro