Как упаковать Python код в дистрибутив: обзор методов

Раздел: Python -> Пакеты

Основные подходы к сборке

Как собрать пакет с помощью современного инструмента python -m build?

Стандартный способ сборки пакетов, рекомендованный PEP 517 и PEP 518, предполагает использование модуля build. Он позволяет создавать как исходные дистрибутивы (sdist), так и колеса (wheels) на основе конфигурации из файла pyproject.toml.

Пошаговая инструкция

  1. Установите пакет build:
    pip install build

    Pip upgrade package python (обновление пакета через pip)

  2. Создайте файл pyproject.toml в корне проекта (пример ниже).
  3. Выполните команду сборки из корня проекта:
    python -m build

    Python pip update package (обновление пакета через pip update)

  4. Готовые дистрибутивы появятся в папке dist/.

Пример минимального pyproject.toml


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

[project]
name = "mypackage"
version = "0.1.0"
description = "Пример простого пакета"
authors = [{name = "Иван Иванов", email = "ivan@example.com"}]
readme = "README.md"
requires-python = ">=3.8"
  

Python build package (сборка пакета python)

После выполнения команды python -m build в папке dist/ появятся файлы mypackage-0.1.0.tar.gz и mypackage-0.1.0-py3-none-any.whl.

Типичные проблемы и их решение:

  • Ошибка "ModuleNotFoundError: No module named 'build'" - забыли установить пакет build. Решение: выполните pip install build.
  • Ошибка синтаксиса в pyproject.toml - например, неправильно указана версия Python. Проверьте формат TOML (используйте двойные кавычки для строк, квадратные скобки для таблиц).
  • Сборка завершается, но пакет не содержит нужных файлов - отсутствует MANIFEST.in или не настроено включение дополнительных файлов. Добавьте в pyproject.toml секцию [tool.setuptools.packages.find] или явно укажите пакеты.

Цель использования: создание универсальных дистрибутивов, совместимых с современными индексами пакетов (PyPI). Рекомендуется для новых проектов.

Вариант 1: Традиционный setup.py

Как собрать пакет с помощью скрипта setup.py?

Классический метод, который работает, если в проекте присутствует файл setup.py с вызовом функции setup() из setuptools. Для сборки используются команды sdist и bdist_wheel.


# setup.py
from setuptools import setup, find_packages

setup(
    name='mypackage',
    version='0.1.0',
    packages=find_packages(),
    install_requires=[],
)
  

Python download package (скачивание пакета python)

Команды для сборки:


python setup.py sdist bdist_wheel
  

Python pip install local package (установка локального пакета через pip)

Возможные проблемы:

  • Команда bdist_wheel может отсутствовать, если не установлен пакет wheel. Установите его: pip install wheel.
  • При использовании с современными версиями setuptools может потребоваться явно указать pyproject.toml даже при наличии setup.py.

Случаи использования: проекты, требующие выполнения произвольного кода в процессе сборки (например, генерация файлов). В современных проектах рекомендуется постепенно переходить на pyproject.toml.

Вариант 2: Настройка через setup.cfg

Как собрать пакет, используя декларативную конфигурацию в setup.cfg?

Альтернатива setup.py - файл setup.cfg, который содержит метаданные и конфигурацию. При этом в проекте всё равно должен присутствовать минимальный setup.py для обратной совместимости.


# setup.cfg
[metadata]
name = mypackage
version = 0.1.0
description = Пример пакета

[options]
packages = find:
  

Python install package version (установка пакета определенной версии в python)

Минимальный setup.py:


from setuptools import setup
setup()
  

модули python linux (модули python в linux)

Сборка выполняется аналогично: python setup.py sdist bdist_wheel или python -m build (если добавлен pyproject.toml).

Цель: разделение конфигурации и кода, упрощение поддержки.

Вариант 3: Использование pyproject.toml без setup.py

Как собрать пакет, используя только pyproject.toml, без setup.py?

Полностью современный подход, соответствующий PEP 517/518. В pyproject.toml указываются система сборки и метаданные, а setup.py не требуется.


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

[project]
name = "mypackage"
version = "0.1.0"
description = "Пакет без setup.py"
  

Сборка выполняется командой python -m build. Этот метод особенно удобен для проектов, не требующих динамической генерации.

Ошибки:

  • Если в pyproject.toml отсутствует обязательная секция [project], сборка завершится с ошибкой ValueError. Проверьте наличие полей name и version.
- Remove python package (удаление пакета python)
- Python pip install windows (установка пакетов pip в windows)
- Python pip windows (установка pip на windows)

Расширенные примеры сборки пакетов

Пример 1: Сборка с указанием дополнительных файлов через MANIFEST.in

Если пакет содержит не только .py-файлы, но и статические ресурсы (изображения, конфиги), их необходимо явно включить.

Пример

# MANIFEST.in
include README.md
include mypackage/data/*.json
recursive-include mypackage/templates *

После добавления MANIFEST.in повторите сборку:

Пример

python -m build
# Результат: файлы из MANIFEST.in попадают в sdist и wheel

Пример 2: Сборка только исходного дистрибутива (sdist)

Иногда требуется только tar.gz. Используйте флаг --sdist:

Пример

python -m build --sdist
# В папке dist/ появится только mypackage-0.1.0.tar.gz

Пример 3: Сборка с указанием версии из переменной окружения

Можно передать версию динамически, используя скрипт, который изменяет pyproject.toml перед сборкой. Например, с помощью sed:

Пример

#!/bin/bash
VERSION="0.2.0"
sed -i "s/version = \".*\"/version = \"$VERSION\"/" pyproject.toml
python -m build

Пример 4: Сборка пакета с зависимостями, указанными в pyproject.toml

Пример

[project]
dependencies = [
    "requests>=2.25",
    "click>=8.0",
]

В процессе сборки зависимости не устанавливаются, они будут подтянуты при установке пакета через pip. Сборка проходит стандартно.

Пример 5: Использование альтернативного бэкенда сборки (Flit)

Вместо setuptools можно применить Flit, который требует меньше конфигурации.

Пример

# pyproject.toml
[build-system]
requires = ["flit_core>=3.2"]
build-backend = "flit_core.buildapi"

[project]
name = "mypackage"
version = "0.1.0"

Сборка:

Пример

python -m build

Такой подход подходит для простых пакетов без сложных расширений на C.

Пример 6: Сборка пакета с нативным расширением (C extension) через setuptools

Пример

# setup.py (обязательно для расширений)
from setuptools import setup, Extension

module = Extension('mypackage.hello', sources=['hello.c'])

setup(
    name='mypackage',
    version='0.1.0',
    ext_modules=[module],
)

Сборка:

Пример

python setup.py build_ext --inplace
python -m build

Результат - колесо, содержащее скомпилированный бинарный модуль под конкретную платформу.

Пример 7: Проверка содержимого собранного колеса

Пример

python -m build
cd dist
unzip -l mypackage-0.1.0-py3-none-any.whl
Archive:  mypackage-0.1.0-py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  12-01-2025 10:00   mypackage/__init__.py
      165  12-01-2025 10:00   mypackage/__init__.py
...

Это позволяет убедиться, что в дистрибутив попали все нужные файлы.

Сборка пакета Python - comments

En
Python build package (python)