Как я могу получить версию, определенную в setup.py
, из моего пакета (для --version
или других целей)?
Чтобы получить версию изнутри вашу пакет во время выполнения (каким появляется ваш вопрос, на самом деле спрашивать), вы можете использовать:
import pkg_resources # part of setuptools
version = pkg_resources.require("MyProject")[0].version
Если вы хотите пойти на другую сторону «раунд (который, кажется, каким другим авторами ответа здесь, кажется, думал, что вы спрашиваете), поставьте строку версии в отдельный файл и прочитайте содержимое файла в . py
.
Вы можете сделать Version.py в вашей пакете с помощью линии __
__, а затем прочитайте его от Setup.py Использование Execfile ('mypackage / version.py')
, так Это устанавливает __ версию __
в пространстве имен SETUP.PY.
Если вы хотите гораздо более простое способом, который будет работать со всеми версиями Python и даже неискристыми языками, которые могут понадобиться доступа к строке версии:
хранить строку версии в качестве единственного содержимого простого текстового файла, названного например версия
и прочитайте этот файл во время Setup.py
.
version_file = open(os.path.join(mypackage_root_dir, 'VERSION'))
version = version_file.read().strip()
То же самое версия
файл будет работать именно в любой другой программе, даже без Python, и вам нужно только изменить строку версии в одном месте для всех программ.
, кстати, не импортируйте свой пакет с вашего Setup.py, как указано в другом ответе здесь: он будет работать для вас (потому что у вас уже установлены зависимости ваших пакетов) , но это будет нанести ущерб новым пользователям вашей пакеты, так как они не смогут установить пакет, не вручную установкой вручную первым.
Ваш вопрос немного расплывчат, но я думаю, что вы спрашиваете, как его уточнить.
Вы должны определить __ версия __
как так:
__version__ = '1.4.4'
И затем вы можете подтвердить, что setup.py знает о версии, которую вы просто определили:
% ./setup.py --version
1.4.4
Лучший способ - определить __версию__
в коде вашего продукта, а затем импортировать его оттуда в setup.py. Это даст вам значение, которое вы сможете прочитать в работающем модуле, и у вас будет только одно место для его определения.
Значения в файле setup.py не устанавливаются, и файл setup.py не остается после установки.
То, что я сделал (например) в coverage.py:
# coverage/__init__.py
__version__ = "3.2"
# setup.py
from coverage import __version__
setup(
name = 'coverage',
version = __version__,
...
)
UPDATE (2017): coverage.py больше не импортирует себя, чтобы получить версию. Импорт собственного кода может сделать его деинсталляционным, потому что код продукта будет пытаться импортировать зависимости, которые еще не установлены, потому что setup.py - это то, что их устанавливает.
Чтобы избежать импорта файла (и, следовательно, выполнения его кода), его можно проанализировать и восстановить атрибут версия
из синтаксического дерева:
# assuming 'path' holds the path to the file
import ast
with open(path, 'rU') as file:
t = compile(file.read(), path, 'exec', ast.PyCF_ONLY_AST)
for node in (n for n in t.body if isinstance(n, ast.Assign)):
if len(node.targets) == 1:
name = node.targets[0]
if isinstance(name, ast.Name) and \
name.id in ('__version__', '__version_info__', 'VERSION'):
v = node.value
if isinstance(v, ast.Str):
version = v.s
break
if isinstance(v, ast.Tuple):
r = []
for e in v.elts:
if isinstance(e, ast.Str):
r.append(e.s)
elif isinstance(e, ast.Num):
r.append(str(e.n))
version = '.'.join(r)
break
Этот код пытается найти __ версия __
] или ВЕРСИЯ
присвоение на верхнем уровне модуля возвращает строковое значение. Правая часть может быть строкой или кортежем.
Создайте файл в исходном дереве, например. в yourbasedir/yourpackage/_version.py. Пусть этот файл содержит только одну строку кода, например:
__version__ = "1.1.0-r4704"
Затем в setup.py откройте этот файл и проанализируйте номер версии следующим образом:
verstr = "unknown" try: verstrline = open('yourpackage/_version.py', "rt").read() except EnvironmentError: pass # Okay, there is no version file. else: VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]" mo = re.search(VSRE, verstrline, re.M) if mo: verstr = mo.group(1) else: raise RuntimeError("unable to find version in yourpackage/_version.py")
] Наконец, в yourbasedir/yourpackage/__init__.py
импортируйте _version следующим образом:
__version__ = "unknown" try: from _version import __version__ except ImportError: # We're running in a tree that doesn't have a _version.py, so we don't know what our version is. pass
Примером кода, который делает это, является пакет "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
в своей настройке.py, но во время запуска py2exe ранее была импортирована другая версия этого пакета. Аналогично, что, если setuptools, easy_install, Distribute или distutils2 пытаются собрать ваш пакет как часть процесса установки другого пакета, который зависит от вашего? Затем можно ли импортировать ваш пакет во время оценки его setup.py, или уже существует версия вашего пакета, которая была импортирована во время жизни этого интерпретатора Python, или требуется ли для импорта вашего пакета сначала установить другие пакеты. , или имеет побочные эффекты, может изменить результаты. У меня было несколько проблем с повторным использованием пакетов Python, которые вызывали проблемы для таких инструментов, как py2exe и setuptools, потому что их setup.py импортирует сам пакет, чтобы найти его номер версии.
Между прочим, этот метод прекрасно сочетается с инструментами для автоматического создания файла yourpackage/_version.py
для вас, например, путем чтения вашей истории контроля версий и записи номера версии на основе наиболее последний тег в истории контроля версий. Вот инструмент, который делает это для darcs: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst и вот фрагмент кода, который делает то же самое для git : http://github.com/warner/python-ecdsa/blob/0ed702a9d4057ecf33eea969b8cf280eaccd89a1/setup.py#L34