Как построить исходный дистрибутив без использования файла setup.py?

10

Со следующей структурой пакета

.
├── my_package
   └── __init__.py
├── setup.cfg
└── setup.py

Содержание setup.py

from setuptools import setup
setup()

Содержание setup.cfg

[metadata]
name = my_package
version = 0.1

[options]
packages = find:

Я могу построить колесо или источник распределения для my_packageэтого

pip wheel --no-deps -w dist .
# generates file ./dist/my_package-0.1-py3-none-any.whl
python setup.py sdist
# generates file ./dist/my_package-0.1.tar.gz

Но, по словам сопровождающего setuptools , декларативная конфигурация сборки идеальна, и использование императивной сборки будет пахнуть кодом. Поэтому мы заменим setup.pyна pyproject.toml:

.
├── my_package
   └── __init__.py
├── setup.cfg
└── pyproject.toml

Содержание pyproject.toml

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

И вы все равно можете построить колесо так же, как и раньше, это работает. Но sdist не работает:

python: can't open file 'setup.py': [Errno 2] No such file or directory

Так как же вам на самом деле собрать файл .tar.gz с помощью setuptools ? Что такое инструмент для создания sdist? Я не хочу менять бэкэнд сборки. Похоже, что все другие инструменты упаковки пишут свои собственные точки входа в сборку, но я думал, что весь смысл определения декларативной системы сборки в метаданных заключается в том, чтобы вам не приходилось практиковаться в системе сборки, изучая, как каждый другой инструмент упаковки ожидает вызова или необходимости входить в интерпретатор и вызывать Python API вручную. Но PEP для требований к системе сборки уже более 2 лет. Я что-то упускаю здесь очевидное?

Как построить исходный дистрибутив без использования setup.pyфайла?

утконос
источник

Ответы:

10

Это несколько спорная тема, и ответ на данный момент заключается в том, что нет единого инструмента, с которым все согласны, является «правильный путь» для создания исходных дистрибутивов, и каким бы он ни был. Вы можете увидеть длинную ветку об этом в дискурсе Python Packaging .

Я не решаюсь дать слишком много советов упаковки в прочных форматах , потому что песок всегда меняется, но по состоянию на ноябрь 2019 года, setup.py sdistявляется не рекомендуется, но это действительно имеет все недостатки , которые PEP 517 и PEP 518 были предназначены для исправления - а именно , что у вас есть создать среду сборки самостоятельно (и знать обо всех зависимостях сборки), и она работает только с setuptools / distutils и их эквивалентами.

Это не «официальная» рекомендация, но текущая лучшая замена для setup.py sdistи setup.py bdist_wheelиспользует версию командной строки pep517. Замена для sdist:

python -m pep517.build --source .

Вы можете одновременно создать колесо и исходный код:

python -m pep517.build --source --binary .

Вот как я собираю свои PEP 517-совместимые пакеты.

Это требует , чтобы ваш проекта есть pyproject.toml, и pyproject.tomlдолжна иметь build-system.requiresи build-system.build-backendключи, но он будет работать для любого проекта с PEP 517-совместимым бэкэндом ( в том числе flit).

Другие инструменты :

Почему бы не использовать flitили poetryили hatch? Все эти инструменты доступны для тех, кто хочет их использовать, но они не являются ответом на этот вопрос . Этот вопрос задают о проектах, построенных с setuptoolsиспользованием декларативного setup.cfgформата. Ни то, flitни другое не poetryдействуют как универсальные внешние интерфейсы сборки PEP 517, и поэтому они работают только как команды сборки для проектов, использующих свои соответствующие внутренние серверы.

Я не достаточно знаком с тем, hatchчтобы сказать, может ли он управлять проектами с бэкэндами, отличными от setuptools, но (опять же, по состоянию на ноябрь 2019 года), это не интерфейс PEP 517, и он не будет работать, если у вас нет а setup.py(это вызовет ошибку «не могу открыть файл setup.py» и проигнорирует ваш pyproject.tomlфайл).

Павел
источник
Зачем сосредотачиваться на том, pep517.buildчто подразумевается только в качестве эксперимента, временной опоры, когда появляются такие продуктивные инструменты, как порхание, поэзия, люк и, возможно, даже больше?
sinoroc
1
Потому что, по моим оценкам, это был успешный эксперимент (я и многие другие пользователи PyPA его используем), так как он имеет правильную семантику для работы, и потому что это единственный интерфейс общего назначения PEP 517, который я знаю. Флит и поэзия вертикально интегрированы в том, что они ожидают, что вы будете использовать их бэкэнд. Люк, кажется, делает много других вещей. pep517.buildэто простой инструмент, созданный именно для этой цели.
Пол
Ах да, хорошая мысль. Я сосредоточился на бэк-эндах сборки. И я действительно думал, что pep517.buildбыл одним из них. Но не совсем, это на самом деле сборка. Также люк не готов PEP517, как я вижу сейчас.
sinoroc
1
Я обновил свой ответ, чтобы ответить на ваш вопрос.
Пол
Да, идеально. Я удаляю свой ответ.
sinoroc
-1

Там нет ничего "очевидного", когда дело доходит до упаковки Python. Действительно, на данный момент, по крайней мере, если вы используете distutils / setuptools, необходимо создать (почти) пустой setup.pyфайл, даже если вы используете полностью декларативный setup.cfg:

#!/usr/bin/env python
from setuptools import setup
setup()

Я также рекомендую chmod +x setup.py.

В этом случае вы просто пишете «точку входа» в систему сборки самостоятельно, и setup()это просто main()функция для нее - но теперь вместо этого setup()можно прочитать все аргументы, которые традиционно передавались setup.cfg.

Теперь вы все еще можете использовать, setup.py sdistесли хотите сделать архив с исходным кодом:

./setup.py sdist

Вы также можете попробовать одну из альтернативных систем сборки, которые включены через pyproject.toml, например, Flit .

Iguananaut
источник
Не уверен, почему за это проголосовали; это в основном правильно, даже если есть другие решения.
Iguananaut
2
Заголовок вопроса: «Как создать исходный дистрибутив без использования файла setup.py?» Этот ответ, кажется, просто демонстрирует «вот как воссоздать тот же файл setup.py, который вы только что удалили», что бесполезно.
утконос
Да, но это было основано на неправильном понимании того, что написание декларативного setup.cfgозначает, что setup.pyбольше нет необходимости использовать setuptools, что не соответствует действительности. То, что название вопроса вводит в заблуждение, не означает, что ответ таков. Они написали в основной части вопроса «Так как же вам на самом деле собрать файл .tar.gz с помощью setuptools ?» который отвечает правильно.
Iguananaut
1
Это на самом деле правда. setuptools не требует файла setup.py, если вы используете PEP 517.
Paul
«если вы используете PEP 517», за исключением большинства людей. Он все еще предварительный и почти не упоминается в package.python.org . Это не то, что у вас будет, если вы не знаете, искать это. Если вы просто хотите, чтобы setuptools работал как обычно, это правильно.
Iguananaut