Создание пакетов Python: руководство от разработки до PyPI
Освойте упаковку Python от кода до развертывания на PyPI
Упаковка Python значительно эволюционировала, и современные инструменты и стандарты делают распространение вашего кода проще, чем когда-либо.
Это руководство проведет вас через создание профессиональных пакетов Python и их публикацию в PyPI. Если вы новичок в Python или вам нужна быстрая справка, ознакомьтесь с нашим Шпаргалкой по Python, чтобы быстро освоить основы Python.

Почему стоит упаковывать ваш код Python?
Упаковка вашего проекта на Python предлагает множество преимуществ:
- Переиспользуемость: Делитесь кодом между несколькими проектами без копирования
- Распространение: Позволяйте другим устанавливать ваш код с помощью простой команды
pip install - Управление зависимостями: Четко указывайте и управляйте зависимостями
- Версионирование: Отслеживайте релизы и поддерживайте обратную совместимость
- Профессиональные стандарты: Следуйте лучшим практикам сообщества Python
- Документация: Структура поощряет правильное документирование и тестирование
Современная структура пакета Python
Хорошо организованный пакет следует этой структуре:
my-package/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── docs/
│ └── index.md
├── .github/
│ └── workflows/
│ └── publish.yml
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
src-layout теперь предпочтительнее плоской структуры, потому что он:
- Предотвращает случайные импорты неустановленного кода во время разработки
- Делает тестирование более надежным, заставляя выполнять установку
- Четко разделяет исходный код и другие файлы проекта
При организации внутренней структуры вашего пакета рассмотрите применение принципов чистой архитектуры, чтобы сделать ваш код более поддерживаемым и тестируемым. Наше руководство по Шаблонам проектирования Python для чистой архитектуры охватывает принципы SOLID, инъекцию зависимостей и шаблоны многослойной архитектуры, которые отлично работают с пакетами Python.
Файл pyproject.toml: Современная конфигурация
pyproject.toml (PEP 518, 621) - это современный стандарт конфигурации проекта Python, заменяющий устаревший setup.py:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "Отличный пакет Python"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Ваше Имя", email = "you@example.com"}
]
keywords = ["пример", "учебник", "пакет"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"black>=23.0.0",
"flake8>=6.0.0",
"mypy>=1.5.0",
]
docs = [
"sphinx>=7.0.0",
"sphinx-rtd-theme>=1.3.0",
]
[project.urls]
Homepage = "https://github.com/yourusername/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/yourusername/mypackage"
Issues = "https://github.com/yourusername/mypackage/issues"
[project.scripts]
mypackage-cli = "mypackage.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
Ключевые разделы конфигурации
- build-system: Указывает бэкенд сборки (setuptools, hatchling, poetry-core, flit-core)
- project: Основные метаданные и зависимости
- project.optional-dependencies: Дополнительные зависимости для функций (разработка, документация, тестирование)
- project.scripts: Точки входа командной строки
- tool.*: Конфигурация для конкретных инструментов (black, pytest, mypy и т.д.)
Выбор бэкенда сборки
Setuptools (Стандартный выбор)
Наиболее широко используемый и совместимый вариант:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
Преимущества: Универсальная совместимость, обширные функции, большое количество плагинов Недостатки: Более громоздкая конфигурация, медленнее, чем новые альтернативы
Hatchling (Современный и быстрый)
Легковесный и производительный современный бэкенд:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Преимущества: Быстрая сборка, простая конфигурация, хорошие настройки по умолчанию Недостатки: Меньше плагинов, чем у setuptools
Poetry (Все-в-одном)
Полное управление зависимостями и окружениями:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "Отличный пакет Python"
authors = ["Ваше Имя <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
Преимущества: Решение зависимостей, файлы блокировки, интегрированный рабочий процесс Недостатки: Различный рабочий процесс, большая поверхность инструмента
Flit (Минималистичный)
Простой инструмент для простых пакетов:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
Преимущества: Очень простой, минимальная конфигурация Недостатки: Ограниченные функции для сложных пакетов
Сборка вашего пакета
Установка инструментов сборки
# Установка современного инструмента сборки
pip install build
# Или для Poetry
pip install poetry
# Или для Hatchling
pip install hatch
Сборка дистрибутивных файлов
Используя пакет build (работает с любым бэкендом):
# Очистка предыдущих сборок
rm -rf dist/ build/ *.egg-info
# Сборка исходного дистрибутива и колеса
python -m build
# Это создает:
# dist/mypackage-0.1.0.tar.gz (исходный дистрибутив)
# dist/mypackage-0.1.0-py3-none-any.whl (колесо)
Используя Poetry:
poetry build
Используя Hatch:
hatch build
Понимание форматов дистрибутивов
Исходный дистрибутив (sdist) - .tar.gz
- Содержит исходный код и инструкции по сборке
- Пип пользователей собирает его во время установки
- Включает тесты, документацию и другие файлы разработки
Колесо - .whl
- Предварительно собранный бинарный дистрибутив
- Быстрая установка (без этапа сборки)
- Платформено-специфичный или чистый Python
- Рекомендуемый формат для распространения
Публикация в PyPI
Метод 1: Ручная загрузка с Twine (Традиционный)
# Установка twine
pip install twine
# Проверка пакета перед загрузкой
twine check dist/*
# Сначала загрузите в TestPyPI (рекомендуется)
twine upload --repository testpypi dist/*
# Тестирование установки из TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage
# Загрузка в производственный PyPI
twine upload dist/*
Настройка учетных данных в ~/.pypirc:
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
Метод 2: Доверенная публикация (Рекомендуется для CI/CD)
Доверенная публикация использует OpenID Connect (OIDC) для аутентификации из платформ CI/CD без хранения токенов.
Настройка в PyPI:
- Перейдите в настройки вашего проекта PyPI
- Перейдите в раздел “Publishing”
- Добавьте нового “pending publisher”
- Настройте:
- Owner: Ваше имя пользователя или организация GitHub
- Repository: Имя репозитория
- Workflow:
publish.yml - Environment:
release(необязательно, но рекомендуется)
GitHub Actions Workflow (.github/workflows/publish.yml):
name: Publish to PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Store distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Download distributions
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Преимущества:
- Нет токенов API для управления и защиты
- Автоматическая аутентификация через OIDC
- Повышенная безопасность за счет правил защиты сред
- Журнал аудита всех публикаций
Лучшие практики
1. Управление версиями
Используйте семантическое версионирование (SemVer): MAJOR.MINOR.PATCH
# Установка инструмента для изменения версий
pip install bump2version
# Изменение версии
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
Настройка в .bumpversion.cfg:
[bumpversion]
current_version = 0.1.0
commit = True
tag = True
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
[bumpversion:file:src/mypackage/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"
2. Включение обязательных файлов
README.md: Четкое описание проекта, инструкции по установке, примеры использования LICENSE: Выберите подходящую лицензию (MIT, Apache 2.0, GPL и т.д.) CHANGELOG.md: Документируйте изменения между версиями .gitignore: Исключите артефакты сборки, кэши, виртуальные окружения
3. Комплексное тестирование
# Установка зависимостей для тестирования
pip install pytest pytest-cov
# Запуск тестов с покрытием
pytest --cov=mypackage tests/
# Генерация отчета о покрытии
pytest --cov=mypackage --cov-report=html tests/
Настройка в pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. Инструменты контроля качества кода
# Форматирование
black src/ tests/
# Проверка кода
flake8 src/ tests/
# Проверка типов
mypy src/
# Сортировка импортов
isort src/ tests/
Интеграция в pre-commit хуки (.pre-commit-config.yaml):
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
5. Документация
Используйте Sphinx для документации:
# Установка Sphinx
pip install sphinx sphinx-rtd-theme
# Инициализация документации
cd docs
sphinx-quickstart
# Сборка документации
make html
Или используйте MkDocs для более простой документации на основе Markdown:
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. Непрерывная интеграция
Тестирование ваших Python-пакетов на разных платформах и в разных средах критически важно для надежности. Для получения информации о производительности Python в разных сценариях развертывания, см. наше сравнение Производительность AWS Lambda: JavaScript vs Python vs Golang, которое исследует производительность Python в серверных средах.
Полный workflow CI/CD (.github/workflows/ci.yml):
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Настройка Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Установка зависимостей
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Запуск тестов
run: pytest --cov=mypackage --cov-report=xml
- name: Загрузка покрытия
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Настройка Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Установка зависимостей
run: |
pip install black flake8 mypy
- name: Проверка форматирования Black
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
Общие проблемы и решения
Проблема 1: Ошибки импорта после установки
Проблема: Пакет установлен, но импорт не работает
Решение: Убедитесь в правильной структуре пакета с файлами __init__.py и правильной настройке pyproject.toml:
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
Проблема 2: Отсутствующие зависимости
Проблема: Пакет устанавливается, но падает при запуске из-за отсутствующих зависимостей
Решение: Укажите все зависимости в pyproject.toml:
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
Проблема 3: Конфликты версий
Проблема: Пакет работает в разработке, но падает в продакшене
Решение: Используйте виртуальные окружения и указывайте минимальные версии:
# Создание изолированного окружения
python -m venv .venv
source .venv/bin/activate # На Windows: .venv\Scripts\activate
# Установка в режиме разработки
pip install -e ".[dev]"
Проблема 4: Большой размер пакета
Проблема: Пакет слишком долго скачивается/устанавливается
Решение: Исключите ненужные файлы с помощью MANIFEST.in:
include README.md
include LICENSE
include pyproject.toml
recursive-include src *.py
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude tests *
recursive-exclude docs *
Проблема 5: Платформенные проблемы
Проблема: Пакет работает на одной ОС, но падает на другой
Решение: Тестируйте на нескольких платформах с помощью матричных сборок CI/CD (см. пример CI выше)
Чек-лист перед публикацией
Перед публикацией пакета в PyPI проверьте:
- Все тесты проходят на разных версиях Python
- Код отформатирован и проверен
- README.md полный с примерами
- Файл LICENSE включен
- Номер версии обновлен
- CHANGELOG.md обновлен
- Зависимости правильно указаны
- Пакет собирается без ошибок (
python -m build) - Пакет протестирован на TestPyPI
- Документация актуальна
- Репозиторий Git помечен версией
- Создан релиз на GitHub (для доверенной публикации)
Дополнительные темы
Точки входа и CLI-инструменты
Создание командной строки:
[project.scripts]
mypackage = "mypackage.cli:main"
Реализация в src/mypackage/cli.py:
import click
@click.command()
@click.option('--name', default='World', help='Имя для приветствия')
def main(name):
"""Пример простого CLI-инструмента"""
click.echo(f'Привет, {name}!')
if __name__ == '__main__':
main()
Для реального примера создания Python-пакетов, взаимодействующих с внешними API, см. наше руководство по Интеграции Ollama с Python, которое демонстрирует создание Python-клиентов с интеграцией как REST API, так и официальной библиотеки.
Системы плагинов
Включение обнаружения плагинов:
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
Расширения на C
Для критического кода:
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
Пространства имен пакетов
Для распределенных пакетов под общим пространством имен:
[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]
[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]
Полезные инструменты и ресурсы
Инструменты разработки пакетов
- cookiecutter: Шаблоны проектов для Python-пакетов
- tox: Автоматизация тестирования на разных версиях Python
- nox: Гибкая альтернатива tox
- pre-commit: Фреймворк для git-хуков качества кода
- commitizen: Стандартизация сообщений коммитов и версионирования
Платформы документации
- Read the Docs: Бесплатный хостинг документации
- GitHub Pages: Хостинг документации MkDocs или Sphinx
- pdoc: Простой генератор документации API
Реестры пакетов
- PyPI: Официальный индекс Python-пакетов (pypi.org)
- TestPyPI: Тестовая среда (test.pypi.org)
- Anaconda.org: Распределение пакетов Conda
- GitHub Packages: Приватный хостинг пакетов
Мониторинг и аналитика
- PyPI Stats: Статистика загрузок пакетов
- Libraries.io: Мониторинг зависимостей и оповещения
- Snyk: Сканирование на уязвимости безопасности
- Dependabot: Автоматические обновления зависимостей
Заключение
Современная упаковка Python стала более дружелюбной для разработчиков с такими стандартами, как pyproject.toml, мощными бэкендами сборки и безопасной публикацией через Trusted Publishing. Следуя этому руководству, вы можете создавать профессиональные, поддерживаемые Python-пакеты, которые эффективно обслуживают ваших пользователей.
Основные выводы:
- Используйте pyproject.toml для всех новых проектов
- Выбирайте подходящий бэкенд сборки для ваших нужд
- Реализуйте автоматизированное тестирование и CI/CD
- Используйте Trusted Publishing для безопасной, безтокенной развертки
- Следуйте семантическому версионированию и ведите changelogs
- Предоставляйте полную документацию и примеры
Экосистема упаковки Python продолжает улучшаться с лучшими инструментами, стандартами и функциями безопасности. Оставайтесь в курсе Python Enhancement Proposals (PEPs) и лучших практик сообщества, чтобы поддерживать ваши пакеты современными и поддерживаемыми.
Полезные ссылки
- Руководство пользователя Python Packaging
- PEP 518 - Указание требований к системе сборки
- PEP 621 - Хранение метаданных проекта в pyproject.toml
- Документация PyPI Trusted Publishing
- Документация Setuptools
- Документация Poetry
- Документация Hatch
- TestPyPI
- GitHub Python Packaging Authority
- Семантическое версионирование
- Выберите лицензию