#python #setuptools
#python #setuptools
Вопрос:
Я пытаюсь создать пакет python, используя конвейер bamboo в нашей рабочей среде.
Чтобы запустить сборку, я должен включить файл build.info.txt
, содержащий номер версии. Этот файл находится на верхнем уровне в репозитории, поэтому структура репозитория выглядит следующим образом
build.info.txt
setup.py
MANIFEST.in
README.md
package/
__init__.py
file1.py
file2.py
Файл build.info.txt
имеет номер версии
version=x.y.z
Я хотел бы использовать этот файл для запуска номера версии, поэтому в __init__.py
I включен простой синтаксический анализатор
from pathlib import Path
path = Path(__file__).absolute().parent / "build.info.txt"
__version__ = open(path).readline()[0].split("=")[-1]
Это отлично работает в локальном режиме. Однако, когда я создаю пакет и отправляю его на наш сервер pypi, я получаю следующую ошибку во время выполнения (т. Е. pip install package
Работает):
FileNotFoundError: [Errno 2] No such file or directory: '</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt'
Я изменил поведение setup.py
(я использую setuptools
), включая:
setup(**other_params, package_data={"": ["../build.info.txt"]}, include_package_data=True)
пока MANIFEST.in
выглядит так
include build.info.txt
Проблема в том, что build.info.txt
using pip install
находится на верхнем уровне:
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/build.info.txt
этот файл является общим для нескольких пакетов, в то время как я хотел бы иметь файл в
</PATH/TO/ENVIRONMENT>/python3.8/site-packages/<PACKAGE>/build.info.txt
(затем мне нужно управлять анализатором __init__
, чтобы проанализировать нужный файл, но это просто)
Как я могу это сделать?
Спасибо
Ответ №1:
Моя рекомендация — использовать importlib.metadata
для чтения версии проекта.
Была попытка формализовать и стандартизировать соглашение о настройке __version__
в PEP 396, но оно так и не получило полного признания. А также в настоящее время эта привычка исчезает, потому что необходимость в этом больше не так остра, благодаря importlib.metadata
. Таким образом, вы можете __version__
полностью удалить и использовать сторонние фрагменты кода, которые хотят знать номер версии вашего приложения или библиотеки importlib.metadata.version('MyProject')
, для его чтения.
Если вы настаиваете на том, чтобы иметь __version__
в своей библиотеке, вы можете изменить это и выполнить следующие действия в своем __init__.py
:
__version__ = importlib.metadata.version('MyProject')
Asides:
-
Если вы настаиваете на работе с файлом
build-info.txt
, вы можете создать символическую ссылку на него в пакете, например, какpackage/build-info.txt
(ссылка наbuild-info.txt
), и__init__.py
можете прочитать этот файл во время выполнения.- Или, как предложено в комментариях, символическая
build-info.txt
ссылка наpackage/build_info.py
, и в__init__.py
:from build_info import version as __version__
(это предполагает, что содержимое этого файла также является допустимым синтаксисом Python).
- Или, как предложено в комментариях, символическая
-
Вы не должны использовать
__file__
для чтения ресурсов данных пакета, это ненадежно, используйтеimportlib.resources
вместо этого (это сделает это гораздо более чистым способом и, при необходимости, позаботится об извлечении файлов в случае архивирования пакета и т. Д.). -
Существуют инструменты, которые могут решить все эти проблемы с номером версии,
setuptools-scm
которые приходят на ум и могут соответствовать вашим потребностям.
Комментарии:
1. Другое предложение для «сторон»
package/build-info.txt
может быть переименованоpackage/version.py
, поэтому строка в__init__.py
становится такой же простой, как:from .version import version as __version__
. А затемsetup.py
автоматически сгенерировать этот файл, используя, например, информацию scm.2. Чтобы завершить мой предыдущий комментарий, см., Например, numpy setup.py , особенно. функция
write_version_py
3. @demi-lune Из того, что я понял из вопроса, имя и местоположение файла являются заданными. Я понял это, поскольку это соглашение из их «бамбуковой» конвейерной среды, и оно не может быть изменено. Возможно, я ошибаюсь (мой ответ также немного вводит в заблуждение, я это исправлю). — Но да,
./setup.py
может читать./build-info.txt
и генерировать./package/version.py
, это может сработать.4. @sinoroc, вы правы: имя и путь исправлены.