Как я могу получить версию, определенную в setup.py
моем пакете (для --version
или других целей)?
python
setuptools
Elmarco
источник
источник
Ответы:
Опросить строку версии уже установленного дистрибутива
Чтобы получить версию из вашего пакета во время выполнения (что, по-видимому, действительно задает ваш вопрос), вы можете использовать:
Сохранить строку версии для использования во время установки
Если вы хотите пойти по другому пути (что, по-видимому, и есть то, о чем другие авторы ответов думали, что вы спрашивали об этом), поместите строку версии в отдельный файл и прочитайте содержимое этого файла
setup.py
.Вы можете сделать version.py в вашем пакете со
__version__
строкой, а затем прочитать его из setup.py, используя егоexecfile('mypackage/version.py')
, чтобы он устанавливался__version__
в пространстве имен setup.py.Если вы хотите гораздо более простой способ, который будет работать со всеми версиями Python и даже с не-Python языками, которым может потребоваться доступ к строке версии:
Сохраните строку версии как единственное содержимое простого текстового файла с именем eg
VERSION
и прочитайте этот файл во времяsetup.py
.Этот же
VERSION
файл будет работать точно так же, как и в любой другой программе, даже не в Python, и вам нужно всего лишь изменить строку версии в одном месте для всех программ.Предупреждение о состоянии гонки во время установки
Между прочим, НЕ импортируйте ваш пакет из вашего setup.py, как это предлагается в другом ответе здесь: он будет работать для вас (потому что у вас уже установлены зависимости вашего пакета), но он нанесет ущерб новым пользователям вашего пакета , так как они не смогут установить ваш пакет без предварительной ручной установки зависимостей.
источник
execfile
работает очень хорошо ... но (к сожалению) не работает с Python 3.with open('mypackage/version.py') as f: exec(f.read())
вместоexecfile('mypackage/version.py')
. (Из stackoverflow.com/a/437857/647002 )пример исследования:
mymodule
Представьте себе эту конфигурацию:
Затем представьте себе обычный сценарий, в котором у вас есть зависимости и он
setup.py
выглядит следующим образом:И пример
__init__.py
:И например
myclasses.py
:проблема № 1: импорт
mymodule
во время установкиЕсли ваш
setup.py
импортmymodule
то во время настройки вы, скорее всего, получитеImportError
. Это очень распространенная ошибка, когда ваш пакет имеет зависимости. Если ваш пакет не имеет других зависимостей, кроме встроенных, вы можете быть в безопасности; Однако это не очень хорошая практика. Причина этого заключается в том, что это не будущее; скажем завтра ваш код должен потреблять некоторые другие зависимости.проблема № 2: где мой
__version__
?Если вы жестко
__version__
вsetup.py
то оно может не совпадать с версией , что вы грузили бы в вашем модуле. Чтобы быть последовательным, вы должны поместить его в одном месте и читать его из того же места, когда вам это нужно. Использованиеimport
вы можете получить проблему # 1.решение: а ля
setuptools
Вы могли бы использовать комбинацию
open
,exec
и обеспечить Dict для тогоexec
чтобы добавить переменные:И в
mymodule/version.py
выставляю версию:Таким образом, версия поставляется вместе с модулем, и у вас не возникает проблем во время установки, когда вы пытаетесь импортировать модуль с отсутствующими зависимостями (еще не установлен).
источник
Лучше всего определить
__version__
код вашего продукта, а затем импортировать его в setup.py оттуда. Это дает вам значение, которое вы можете прочитать в своем работающем модуле, и у вас есть только одно место для его определения.Значения в setup.py не установлены, и setup.py не остается после установки.
Что я сделал (например) в cover.py:
ОБНОВЛЕНИЕ (2017): cover.py больше не импортирует себя, чтобы получить версию. Импорт собственного кода может сделать его неустранимым, потому что код вашего продукта будет пытаться импортировать зависимости, которые еще не установлены, потому что именно их устанавливает файл setup.py.
источник
__version__
в нем, каким-то образом поврежден, то ваш импорт также будет поврежден. Python не знает, как интерпретировать только те выражения, которые вы хотите. @pjeby прав: если вашему модулю нужно импортировать другие модули, они могут быть еще не установлены, и это будет хаотично. Этот метод работает, если вы осторожны, что при импорте не возникает длинная цепочка других импортов.pip install <packagename>
я получаю следующую ошибку:ImportError: No module named <packagename>
. Пожалуйста, ПРЕДУПРЕЖДАЙТЕ своим читателям, что вы не можете запускать файлы setup.py, подобные этим, в тех средах, где пакет еще не установлен!Ваш вопрос немного расплывчат, но я думаю, что вы спрашиваете, как его задать.
Вам нужно определить
__version__
так:И тогда вы можете подтвердить, что setup.py знает о версии, которую вы только что указали:
источник
Я не был доволен этими ответами ... не хотел требовать setuptools или создавать отдельный модуль для одной переменной, поэтому я придумал это.
Если вы уверены, что основной модуль выполнен в стиле pep8 и останется таким:
Если вы хотите быть очень осторожным и использовать настоящий парсер:
setup.py является своего рода одноразовым модулем, поэтому не проблема, если он немного уродлив.
Обновление: достаточно забавно, я отошел от этого в последние годы и начал использовать отдельный файл в пакете под названием
meta.py
. Я поместил там много метаданных, которые я мог бы захотеть часто менять. Таким образом, не только для одного значения.источник
ast.get_docstring()
с некоторыми и.split('\n')[0].strip()
т. Д. Для автоматического заполнения изdescription
источника. Одна вещь меньше , чтобы держать в синхронизацииСоздайте файл в вашем исходном дереве, например, в yourbasedir / yourpackage / _version.py. Пусть этот файл содержит только одну строку кода, например:
__version__ = "1.1.0-r4704"
Затем в вашем файле setup.py откройте этот файл и проанализируйте номер версии следующим образом:
Наконец, в
yourbasedir/yourpackage/__init__.py
_version импорта вот так:Примером кода, который делает это, является пакет "pyutil", который я поддерживаю. (См. PyPI или поиск в Google - stackoverflow запрещает мне включать гиперссылку на него в этом ответе.)
@pjeby прав, что вы не должны импортировать свой пакет из его собственного setup.py. Это сработает, когда вы протестируете его, создав новый интерпретатор Python и выполнив в нем setup.py
python setup.py
, но в некоторых случаях это не сработает. Это потому,import youpackage
что не означает чтение текущего рабочего каталога для каталога с именем «yourpackage», это означает поиск в текущемsys.modules
ключе «yourpackage» и затем выполнение различных действий, если его там нет. Так что это всегда работает, когда вы делаете,python setup.py
потому что у вас свежий, пустойsys.modules
, но это не работает в целом.Например, что если py2exe выполняет ваш setup.py как часть процесса упаковки приложения? Я видел такой случай, когда py2exe поместил бы неправильный номер версии в пакет, потому что пакет получал свой номер версии от
import myownthing
в его setup.py, но другая версия этого пакета была ранее импортирована во время запуска py2exe. Аналогичным образом, что если setuptools, easy_install, distribution или distutils2 пытаются собрать ваш пакет как часть процесса установки другого пакета, который зависит от вашего? Затем, будет ли ваш пакет импортируемым во время оценки его setup.py, или уже существует версия вашего пакета, которая была импортирована в течение жизни этого интерпретатора Python, или для импорта вашего пакета сначала должны быть установлены другие пакеты. или имеет побочные эффекты, может изменить результаты. У меня было несколько попыток повторно использовать пакеты Python, что вызывало проблемы для таких инструментов, как py2exe и setuptools, потому что их setup.py импортирует сам пакет, чтобы найти его номер версии.Кстати, эта техника прекрасно работает с инструментами для автоматического создания
yourpackage/_version.py
файла для вас, например, читая историю контроля версий и записывая номер версии на основе самого последнего тега в истории контроля версий. Вот инструмент, который делает это для дарков: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst, а также фрагмент кода, который делает то же самое для git: http: // github .com / Уорнер / питон-ECDSA / BLOB / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34источник
Это также должно работать, используя регулярные выражения и в зависимости от полей метаданных иметь такой формат:
Используйте следующее в начале вашего setup.py:
После этого вы можете использовать метаданные в вашем скрипте следующим образом:
источник
С такой структурой:
где version.py содержит:
Вы можете сделать это в setup.py :
Это не вызовет никаких проблем с зависимостями, которые у вас есть в вашем mymodule / __ init__.py
источник
Чтобы избежать импорта файла (и, следовательно, выполнения его кода), можно проанализировать его и восстановить
version
атрибут из синтаксического дерева:Этот код пытается найти присваивание
__version__
orVERSION
на верхнем уровне модуля, возвращающее строковое значение. Правая сторона может быть либо строкой, либо кортежем.источник
Есть тысяча способов снять шкуру с кошки - вот мой:
источник
Очистка https://stackoverflow.com/a/12413800 от @ gringo-suave:
источник
Теперь это грубо и нуждается в некоторой доработке (возможно, в pkg_resources я пропустил непокрытый вызов члена, но я просто не понимаю, почему это не работает, и почему никто не предложил его на сегодняшний день (поиск в Google не включил это) ... обратите внимание, что это Python 2.x, и для него потребуется pkg_resources (sigh):
источник
Мы хотели поставить мета информацию о нашем пакете
pypackagery
в__init__.py
, но не мог , так как он имеет зависимости сторонних , как PJ Эби уже отмечали (см его ответ и предупреждение относительно состояния гонки).Мы решили это, создав отдельный модуль,
pypackagery_meta.py
который содержит только метаинформацию:затем импортировал метаинформацию в
packagery/__init__.py
:и, наконец, использовал его в
setup.py
:Вы должны включить
pypackagery_meta
в свой пакет сpy_modules
аргументом настройки. В противном случае вы не сможете импортировать его после установки, так как в упакованном дистрибутиве его не будет.источник
Просто и понятно, создайте файл
source/package_name/version.py
с таким содержимым:Затем в своем файле
source/package_name/__init__.py
вы импортируете версию для использования другими людьми:Теперь вы можете надеть это
setup.py
Испытано это с Python
2.7
,3.3
,3.4
,3.5
,3.6
и3.7
на Linux, Windows и Mac OS. Я использовал пакет, в котором есть Интеграция и Модульные тесты для всех этих платформ. Вы можете увидеть результаты.travis.yml
иappveyor.yml
здесь:Альтернативная версия использует менеджер контекста:
Вы также можете использовать
codecs
модуль для обработки ошибок Unicode как на Python, так2.7
и на Python.3.6
Если вы пишете модуль Python на 100% на C / C ++ с использованием расширений Python C, вы можете сделать то же самое, но с использованием C / C ++ вместо Python.
В этом случае создайте следующее
setup.py
:Который читает версию из файла
version.h
:Но не забудьте создать файл
MANIFEST.in
для включенияversion.h
:И он интегрирован в основное приложение с:
Ссылки:
источник
развернуть пакет на сервере и соглашение об именах файлов для пакетов индексов:
пример преобразования динамической версии в пипсах:
выиграть:
макинтош:
Найдите образец setup.py вызывает динамическое соответствие версии пипа из git commit
источник
Я использую переменную среды, как показано ниже
ВЕРСИЯ = 0.0.0 python setup.py sdist bdist_wheel
В setup.py
Для проверки согласованности с версией упаковщика я использую приведенный ниже скрипт.
источник