Есть ли стандартный способ связать строку версии с пакетом Python таким образом, чтобы я мог сделать следующее?
import foo
print foo.version
Я хотел бы представить, что есть какой-то способ получить эти данные без какого-либо дополнительного жесткого кодирования, поскольку второстепенные / второстепенные строки уже указаны setup.py
. Альтернативное решение, которое я нашел, должно было быть import __version__
в моем, foo/__init__.py
а затем __version__.py
сгенерировано setup.py
.
setup.py
. Смотрите этот вопрос .Ответы:
Не является прямым ответом на ваш вопрос, но вы должны рассмотреть вопрос о его названии
__version__
, а неversion
.Это почти квази-стандарт. Многие модули в стандартной библиотеке используют
__version__
, и это также используется во многих сторонних модулях, так что это квази-стандарт.Обычно
__version__
это строка, но иногда это также float или кортеж.Отредактируйте: как упомянуто С.Лоттом (Спасибо!), PEP 8 говорит это явно
Вам также следует убедиться, что номер версии соответствует формату, описанному в PEP 440 ( PEP 386, предыдущая версия этого стандарта).
источник
__version_info__
конкретно? (Который «придумывает» ваше собственное двойное подчеркивание.) [Когда Джеймс комментировал, подчеркивания ничего не делали в комментариях, теперь они указывают на акцент, поэтому Джеймс действительно написал__version_info__
тоже. --- ред.]Я использую один
_version.py
файл как «некогда каноническое место» для хранения информации о версии:Это обеспечивает
__version__
атрибут.Он предоставляет стандартную версию метаданных. Поэтому он будет обнаружен
pkg_resources
или другими инструментами, которые анализируют метаданные пакета (EGG-INFO и / или PKG-INFO, PEP 0345).Он не импортирует ваш пакет (или что-либо еще) при сборке пакета, что может вызвать проблемы в некоторых ситуациях. (См. Комментарии ниже о том, какие проблемы это может вызвать.)
Номер версии записывается только в одном месте, поэтому есть только одно место, где его можно изменить при изменении номера версии, и вероятность несовместимости версий меньше.
Вот как это работает: «одно каноническое место» для хранения номера версии - это файл .py с именем «_version.py», который находится в вашем пакете Python, например, в
myniftyapp/_version.py
. Этот файл является модулем Python, но ваш setup.py не импортирует его! (Это побеждает функцию 3.) Вместо этого ваш setup.py знает, что содержимое этого файла очень просто, что-то вроде:Итак, ваш setup.py открывает файл и анализирует его с помощью следующего кода:
Затем ваш setup.py передает эту строку в качестве значения аргумента «версия»
setup()
, тем самым удовлетворяя функции 2.Чтобы удовлетворить функцию 1, вы можете сделать так, чтобы ваш пакет (во время выполнения, а не во время установки!) Импортировал файл _version
myniftyapp/__init__.py
примерно так:Вот пример этой техники, которую я использовал годами.
Код в этом примере немного сложнее, но упрощенный пример, который я написал в этом комментарии, должен быть полной реализацией.
Вот пример кода импорта версии .
Если вы видите что-то не так с этим подходом, пожалуйста, дайте мне знать.
источник
setup.py
. Кроме того, если он попытается выполнить полную глубину и выполнить все операции deps, прежде чем он сделает это, он застрянет, если будут циклические операции deps. Но если он попытается собрать этот пакет перед установкой зависимостей, то, если вы импортируете свой пакет из своегоsetup.py
, он не обязательно сможет импортировать свои deps или правильные версии своих deps.execfile("myniftyapp/_version.py")
изнутри setup.py, а не пытаться анализировать код версии вручную. Предложено в stackoverflow.com/a/2073599/647002 - обсуждение там также может быть полезным.Переписан 2017-05
После более чем десяти лет написания кода на Python и управления различными пакетами я пришел к выводу, что DIY, возможно, не лучший подход.
Я начал использовать
pbr
пакет для работы с версиями в моих пакетах. Если вы используете git в качестве SCM, это будет вписываться в ваш рабочий процесс как волшебство, сохраняя ваши недели работы (вы будете удивлены, насколько сложной может быть проблема).На сегодняшний день pbr занимает 11-е место по популярности среди пакетов python, и достижение этого уровня не включало никаких хитростей: было только одно: очень просто решить проблему с упаковкой.
pbr
может нести больше бремени обслуживания пакета, не ограничивается версионированием, но не заставляет вас использовать все его преимущества.Итак, чтобы дать вам представление о том, как выглядит использование pbr в одном коммите, взгляните на упаковку в pbr
Вероятно, вы заметили, что версия не хранится вообще в хранилище. PBR обнаруживает это по веткам и тегам Git.
Не нужно беспокоиться о том, что происходит, когда у вас нет git-репозитория, потому что pbr «компилирует» и кэширует версию, когда вы упаковываете или устанавливаете приложения, так что нет никакой зависимости во время выполнения от git.
Старое решение
Вот лучшее решение, которое я видел до сих пор, и оно также объясняет, почему:
Внутри
yourpackage/version.py
:Внутри
yourpackage/__init__.py
:Внутри
setup.py
:Если вы знаете другой подход, который кажется лучше, дайте мне знать.
источник
from .version import __version__
в setup.py?setup.py
работы - попробуйте, вы получите ошибку (или, по крайней мере, я сделал :-))В соответствии с отложенным PEP 396 (номерами версий модулей) , существует предложенный способ сделать это. Он описывает с обоснованием (по общему признанию необязательный) стандарт для модулей, которым необходимо следовать. Вот фрагмент кода:
источник
Хотя это, вероятно, слишком поздно, есть несколько более простая альтернатива предыдущему ответу:
(И было бы довольно просто преобразовать автоматически увеличивающиеся части номеров версий в строку, используя
str()
.)Конечно, из того, что я видел, люди склонны использовать что-то похожее на ранее упомянутую версию при использовании
__version_info__
, и поэтому хранят ее как кортеж целых чисел; однако я не совсем вижу в этом смысла, так как сомневаюсь, что бывают ситуации, когда вы выполняете математические операции, такие как сложение и вычитание частей номеров версий для любых целей, кроме любопытства или автоматического увеличения (и даже тогда,int()
иstr()
может быть использован довольно легко). (С другой стороны, существует вероятность того, что чей-то код ожидает числовой кортеж, а не строковый кортеж, и, следовательно, не сможет.)Это, конечно же, мое собственное мнение, и я с удовольствием хотел бы, чтобы мнение других об использовании числового кортежа.
Как Шези напомнил мне, (лексические) сравнения числовых строк не обязательно имеют тот же результат, что и прямые численные сравнения; для этого потребуются ведущие нули. Таким образом, в конце концов, сохранение
__version_info__
(или как бы это ни называлось) в виде набора целочисленных значений позволило бы более эффективно сравнивать версии.источник
__version_info__ = (1,2,3)
__version_info__ = (0, 1, 0) __version__ = '.'.join(map(str, __version_info__))
__version__ = '.'.join(__version_info__)
том, что__version_info__ = ('1', '2', 'beta')
станет1.2.beta
, а не1.2beta
или1.2 beta
Многие из этих решений здесь игнорируют
git
теги версии, что по-прежнему означает, что вам нужно отслеживать версию в нескольких местах (плохо). Я подошел к этому со следующими целями:git
репозиторииgit tag
/push
иsetup.py upload
шаги с помощью одной команды, которая не требует ввода.Как это устроено:
По
make release
команде, последняя помеченная версия в git-репо будет найдена и увеличена. Тег отодвинут назадorigin
.В
Makefile
магазинах версии вsrc/_version.py
которой он будет прочитан ,setup.py
а также включены в выпуск. Не проверяйте_version.py
в системе контроля версий!setup.py
Команда читает строку новой версии изpackage.__version__
.Подробности:
Makefile
release
Цель всегда увеличивает 3 - й версии цифру, но вы можете использоватьnext_minor_ver
илиnext_major_ver
для увеличения других цифр. Команды опираются наversionbump.py
скрипт, который проверяется в корне репоversionbump.py
Это делает тяжелую работу, как обрабатывать и увеличивать номер версии с
git
.__init__.py
my_module/_version.py
Файл импортируется вmy_module/__init__.py
. Поместите сюда любую статическую конфигурацию установки, которую вы хотите распространять вместе с вашим модулем.setup.py
Последний шаг - прочитать информацию о версии из
my_module
модуля.Конечно, для того, чтобы все это работало, в репо должен быть хотя бы один тег версии.
источник
versionbump.py
когда у нас есть замечательный пакет bumpversion для python._version.py
следует отслеживать контроль версий?Я использую файл JSON в каталоге dir. Это соответствует требованиям Zooko.
Внутри
pkg_dir/pkg_info.json
:Внутри
setup.py
:Внутри
pkg_dir/__init__.py
:Я также помещаю другую информацию
pkg_info.json
, как автор. Мне нравится использовать JSON, потому что я могу автоматизировать управление метаданными.источник
Также стоит отметить, что это
__version__
не только полуслова. в Python также есть__version_info__
кортеж, в простых случаях вы можете просто сделать что-то вроде:... и вы можете получить
__version__
строку из файла или что-то еще.источник
__version_info__
?__version_info__ = (1, 2, 3)
и__version__ = '.'.join(map(str, __version_info__))
).__version__ = '.'.join(str(i) for i in __version_info__)
немного длиннее, но более питонно.i
не имеет смысла,version_num
немного длинно и неоднозначно ...). Я даже воспринимаю существованиеmap()
в Python как сильный намек на то, что его следует использовать здесь, так как здесь нам нужно сделать типичный примерmap()
использования (использовать с существующей функцией) - я не вижу много других разумных применений.Кажется, не существует стандартного способа встроить строку версии в пакет Python. Большинство пакетов, которые я видел, используют какой-то вариант вашего решения, например, eitner.
Вставьте версию
setup.py
иsetup.py
создайте модуль (напримерversion.py
), содержащий только информацию о версии, импортированную вашим пакетом, илиОбратное: поместите информацию о версии в сам пакет и импортируйте ее , чтобы установить версию в
setup.py
источник
стрелка обрабатывает это интересным способом.
Сейчас (с 2e5031b )
В
arrow/__init__.py
:В
setup.py
:Перед
В
arrow/__init__.py
:В
setup.py
:источник
file_text
?pip install -e .
ветки разработки или чего-то еще при тестировании. setup.py абсолютно не должен полагаться на импорт пакета, который находится в процессе установки, чтобы определить параметры для развертывания. Хлоп.Я также видел другой стиль:
источник
.VERSION
не означает, что вам не нужно реализовывать__version__
.django
в проекте?Использование
setuptools
иpbr
Не существует стандартного способа управления версиями, но стандартным способом управления вашими пакетами является
setuptools
.Лучшее решение, которое я нашел в целом для управления версией, это использовать
setuptools
сpbr
расширением. Теперь это мой стандартный способ управления версией.Настройка вашего проекта для полной упаковки может быть излишней для простых проектов, но если вам нужно управлять версией, вы, вероятно, на правильном уровне, чтобы просто все настроить. Это также делает ваш пакет повторно выпускаемым на PyPi, так что каждый может загрузить его и использовать с Pip.
PBR перемещает большинство метаданных из
setup.py
инструментов вsetup.cfg
файл, который затем используется в качестве источника для большинства метаданных, которые могут включать версию. Это позволяет упаковать метаданные в исполняемый файл, используя что-то вроде этогоpyinstaller
(если это так, вам, вероятно, понадобится эта информация ), и отделить метаданные от других сценариев управления / настройки пакетов. Вы можете напрямую обновить строку версииsetup.cfg
вручную, и она будет перенесена в*.egg-info
папку при сборке выпусков вашего пакета. Затем ваши сценарии могут получить доступ к версии из метаданных, используя различные методы (эти процессы описаны в разделах ниже).При использовании Git для VCS / SCM эта настройка еще лучше, поскольку она будет извлекать большую часть метаданных из Git, так что ваше хранилище может стать вашим основным источником правды для некоторых метаданных, включая версию, авторов, журналы изменений, и т.д. Специально для версии, он создаст строку версии для текущего коммита на основе тегов git в репозитории.
setup.py
иsetup.cfg
файл с метаданными.Поскольку PBR будет извлекать версию, автора, журнал изменений и другую информацию непосредственно из вашего git-репо, поэтому некоторые из метаданных
setup.cfg
могут быть опущены и автоматически сгенерированы при создании дистрибутива для вашего пакета (с использованиемsetup.py
)Текущая версия в реальном времени
setuptools
будет получать последнюю информацию в режиме реального времени, используяsetup.py
:Последняя версия будет извлечена из
setup.cfg
файла или из репозитория git, основываясь на последней сделанной фиксации и тегах, существующих в репо. Эта команда не обновляет версию в дистрибутиве.Обновление версии
Когда вы создаете дистрибутив с помощью
setup.py
(напримерpy setup.py sdist
, например), тогда вся текущая информация будет извлечена и сохранена в дистрибутиве. По сути, это запускаетsetup.py --version
команду, а затем сохраняет информацию о версии вpackage.egg-info
папке в наборе файлов, в которых хранятся метаданные распространения.Доступ к версии из скрипта
Вы можете получить доступ к метаданным из текущей сборки в скриптах Python в самом пакете. Например, для версии есть несколько способов сделать это:
Вы можете поместить один из них непосредственно в свой
__init__.py
пакет для извлечения информации о версии следующим образом, аналогично некоторым другим ответам:источник
После нескольких часов попыток найти простейшее надежное решение, вот части:
создайте файл version.py ВНУТРИ папки вашего пакета "/ mypackage":
в setup.py:
в основной папке init .py:
exec()
Функция запускает сценарий вне какого - либо импорта, так как setup.py запускается до модуля может быть импортирован. Вам все еще нужно управлять номером версии в одном файле в одном месте, но, к сожалению, его нет в файле setup.py. (это недостаток, но недостаток импорта - это плюс)источник
С тех пор, как этот вопрос впервые был задан, была проделана большая работа по унификации версий и поддержке соглашений . Возможные варианты теперь подробно описаны в Руководстве пользователя по упаковке Python . Также следует отметить, что схемы нумерации версий в Python относительно строгие в соответствии с PEP 440 , и поэтому сохранение нормальных вещей крайне важно, если ваш пакет будет выпущен в Cheese Shop .
Вот сокращенная разбивка вариантов управления версиями:
setup.py
( setuptools ) и получите версию.__init__.py
как исходного кода), например, bump2version , changes или zest.releaser .__version__
глобальной переменной в определенном модуле.setup.py
релиз и используйте importlib.metadata, чтобы получить его во время выполнения. (Предупреждение, есть версии до 3.8 и после 3.8.)__version__
вsample/__init__.py
и импортируйте образец вsetup.py
.Обратите внимание, что (7) может быть самым современным подходом (метаданные сборки не зависят от кода, публикуемого автоматизацией). Также ОБРАТИТЕ ВНИМАНИЕ, что если для выпуска пакета используется установка, то простой
python3 setup.py --version
будет сообщать о версии напрямую.источник
Для чего стоит, если вы используете NumPy distutils,
numpy.distutils.misc_util.Configuration
естьmake_svn_version_py()
метод, который встраивает номер ревизии внутрьpackage.__svn_version__
переменнойversion
.источник
version.py
файл только с__version__ = <VERSION>
параметром в файле. Вsetup.py
файле импортируйте__version__
параметр и поместите его значение вsetup.py
файл следующим образом:version=__version__
setup.py
файл сversion=<CURRENT_VERSION>
- CURRENT_VERSION жестко закодирован.Поскольку мы не хотим вручную изменять версию в файле каждый раз, когда создаем новый тег (готовый выпустить новую версию пакета), мы можем использовать следующее:
Я очень рекомендую упаковку с защитой от ударов . Я использовал его в течение многих лет, чтобы поднять версию.
начните с добавления
version=<VERSION>
в вашsetup.py
файл, если у вас его еще нет.Вы должны использовать такой короткий скрипт каждый раз, когда вы поднимаете версию:
Затем добавьте один файл в репо
.bumpversion.cfg
:Примечание:
__version__
параметр вversion.py
файле, как это было предложено в других сообщениях, и обновить файл bumpversion следующим образом:[bumpversion:file:<RELATIVE_PATH_TO_VERSION_FILE>]
git commit
илиgit reset
все в своем репо, иначе вы получите грязную ошибку репо.источник
bumpversion
, без которого он не будет работать. Используйте последнюю версию.version.py
или отслеживать ееbumpversion
?__version__
сохраняют значение параметра в файле setup.py. Мое решение используется в производстве, и это обычная практика. Примечание: просто для ясности, использование bumpversion как части скрипта - лучшее решение, поместите его в свой CI, и это будет автоматическая операция.Если вы используете CVS (или RCS) и хотите быстрое решение, вы можете использовать:
(Конечно, номер редакции будет заменен на CVS.)
Это дает вам версию для печати и информацию о версии, которую вы можете использовать для проверки того, что импортируемый вами модуль имеет по крайней мере ожидаемую версию:
источник
__version__
в? Как можно увеличить номер версии с помощью этого решения?