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

Как собрать Package из кода Python?

1.0 Junior🔥 101 комментариев
#Python Core

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

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

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

# Как собрать Package из кода Python?

Обзор процесса

Сборка Python пакета (package) — это процесс подготовки кода к распределению через PyPI или локально. Современный стандарт использует pyproject.toml с build backends (build, hatchling, poetry, setuptools).

Вариант 1: Современный подход (рекомендуемый)

Используем pyproject.toml с инструментом build.

Шаг 1: Структура проекта

my_package/
├── pyproject.toml
├── README.md
├── LICENSE
└── src/
    └── my_package/
        ├── __init__.py
        ├── module1.py
        └── module2.py

Шаг 2: pyproject.toml

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-package"
version = "0.1.0"
description = "Short description"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
    {name = "Your Name", email = "you@example.com"}
]
classifiers = [
    "Development Status :: 3 - Alpha",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.8",
    "Programming Language :: Python :: 3.9",
]

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

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

[tool.hatch.version]
path = "src/my_package/__init__.py"
pattern = '__version__ = "(?P<version>[^"]+)"'

Шаг 3: init.py

__version__ = "0.1.0"

from .module1 import function1
from .module2 import function2

__all__ = ["function1", "function2"]

Шаг 4: Установить build

pip install build twine

Шаг 5: Собрать пакет

python -m build

Результат:

dist/
├── my_package-0.1.0.tar.gz  # Source distribution (sdist)
└── my_package-0.1.0-py3-none-any.whl  # Wheel (binary distribution)

Шаг 6: Проверить пакет

twine check dist/*

Шаг 7: Загрузить на PyPI

# На TestPyPI (для проверки)
twine upload --repository testpypi dist/*

# На PyPI (production)
twine upload dist/*

Вариант 2: С использованием setuptools

Это старый подход, но всё ещё распространённый.

setup.py

from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setup(
    name="my-package",
    version="0.1.0",
    author="Your Name",
    author_email="you@example.com",
    description="Short description",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/yourname/my-package",
    packages=find_packages(where="src"),
    package_dir={"": "src"},
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires=">=3.8",
    install_requires=[
        "requests>=2.25.0",
    ],
    extras_require={
        "dev": ["pytest", "black"],
    },
)

Собрать

python setup.py sdist bdist_wheel

Вариант 3: С Poetry

Поэтичный и удобный способ.

pyproject.toml (Poetry)

[tool.poetry]
name = "my-package"
version = "0.1.0"
description = "Short description"
authors = ["Your Name <you@example.com>"]
readme = "README.md"
license = "MIT"
repository = "https://github.com/yourname/my-package"

[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.25.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.0"
black = "^22.0"

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

Собрать

poetry build

Полный пример: практический пакет

Структура

my_calculator/
├── pyproject.toml
├── README.md
├── LICENSE
├── src/
│   └── my_calculator/
│       ├── __init__.py
│       ├── calculator.py
│       └── utils.py
└── tests/
    ├── test_calculator.py
    └── test_utils.py

src/my_calculator/init.py

__version__ = "0.1.0"
__author__ = "Your Name"

from .calculator import Calculator
from .utils import format_result

__all__ = ["Calculator", "format_result"]

src/my_calculator/calculator.py

class Calculator:
    """Simple calculator class."""
    
    @staticmethod
    def add(a: float, b: float) -> float:
        """Add two numbers."""
        return a + b
    
    @staticmethod
    def multiply(a: float, b: float) -> float:
        """Multiply two numbers."""
        return a * b

src/my_calculator/utils.py

def format_result(value: float, decimals: int = 2) -> str:
    """Format number to string."""
    return f"{value:.{decimals}f}"

pyproject.toml (полный пример)

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-calculator"
version = "0.1.0"
description = "Simple calculator package"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
    {name = "Your Name", email = "you@example.com"}
]
keywords = ["calculator", "math"]
classifiers = [
    "Development Status :: 3 - Alpha",
    "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",
]

[project.urls]
Homepage = "https://github.com/yourname/my-calculator"
Repository = "https://github.com/yourname/my-calculator.git"
Issues = "https://github.com/yourname/my-calculator/issues"

[project.optional-dependencies]
dev = ["pytest>=7.0", "pytest-cov", "black", "ruff", "mypy"]

[tool.hatch.version]
path = "src/my_calculator/__init__.py"

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "--cov=src/my_calculator --cov-report=html"

[tool.black]
line-length = 88
target-version = ["py38"]

[tool.ruff]
line-length = 88
target-version = "py38"
select = ["E", "F", "W"]

Команды для сборки и публикации

Сборка

# Установить инструменты
pip install build twine

# Собрать
python -m build

# Проверить содержимое
ls -la dist/

# Проверить метаданные
twine check dist/*

Локальная установка для тестирования

# Установить в режиме разработки
pip install -e .

# Установить с доп. зависимостями
pip install -e ".[dev]"

# Тестировать
pytest

# Проверить линтинг
black --check src/
ruff check src/

Публикация

# Загрузить на TestPyPI
twine upload --repository testpypi dist/*

# Проверить на TestPyPI
pip install --index-url https://test.pypi.org/simple/ my-package==0.1.0

# Загрузить на PyPI
twine upload dist/*

Что входит в пакет

Wheel (.whl)

  • Бинарный дистрибутив (быстро устанавливается)
  • Платформозависимый (python, os, architecture)
  • Предпочитается для установки

Source Distribution (.tar.gz)

  • Исходный код
  • Кроссплатформенный
  • Требует компиляции при установке

Best Practices

  1. Используй pyproject.toml (PEP 517/518) вместо setup.py
  2. Структура src/ — разделение между кодом и тестами
  3. Версионирование: используй семантическое версионирование (MAJOR.MINOR.PATCH)
  4. Зависимости: указывай минимальные требования, не максимальные
  5. Тестирование: включи тесты перед публикацией
  6. Documentation: README.md, docstrings, примеры кода
  7. License: всегда указывай лицензию
  8. Type hints: добавляй py.typed маркер для типов

Вывод

Современный способ собрать пакет Python:

  1. Структурируй проект с src/ директорией
  2. Напиши pyproject.toml с metadata
  3. Запусти python -m build
  4. Проверь с twine check
  5. Загрузи на PyPI с twine upload
Как собрать Package из кода Python? | PrepBro