是否有一种标准的方法将版本字符串与Python包相关联,以便我可以执行以下操作?
import foo
print(foo.version)
我认为有一些方法可以在没有任何额外硬编码的情况下检索数据,因为minor/major字符串已经在setup.py中指定了。我发现的替代解决方案是在我的foo/__init__.py中导入__version__,然后由setup.py生成__version__.py。
是否有一种标准的方法将版本字符串与Python包相关联,以便我可以执行以下操作?
import foo
print(foo.version)
我认为有一些方法可以在没有任何额外硬编码的情况下检索数据,因为minor/major字符串已经在setup.py中指定了。我发现的替代解决方案是在我的foo/__init__.py中导入__version__,然后由setup.py生成__version__.py。
当前回答
如果您使用CVS(或RCS)并想要快速解决方案,您可以使用:
__version__ = "$Revision: 1.1 $"[11:-2]
__version_info__ = tuple([int(s) for s in __version__.split(".")])
(当然,修订号会被CVS代替)
这为您提供了一个打印友好的版本和版本信息,您可以使用它来检查您正在导入的模块至少具有预期的版本:
import my_module
assert my_module.__version_info__ >= (1, 1)
其他回答
无论如何,如果你使用NumPy distutils, NumPy .distutils.misc_util。Configuration有一个make_svn_version_py()方法,它将版本号嵌入到包中。变量version中的__svn_version__。
自从第一次提出这个问题以来,已经完成了许多关于统一版本和支持约定的工作。可接受的选项现在在Python打包用户指南中详细介绍。同样值得注意的是,版本号方案在Python PEP 440中是相对严格的,因此如果您的包将被发布到Cheese Shop,那么保持正常是至关重要的。
以下是版本控制选项的简短分类:
Read the file in setup.py (setuptools) and get the version. Use an external build tool (to update both __init__.py as well as source control), e.g. bump2version, changes or zest.releaser. Set the value to a __version__ global variable in a specific module. Place the value in a simple VERSION text file for both setup.py and code to read. Set the value via a setup.py release, and use importlib.metadata to pick it up at runtime. (Warning, there are pre-3.8 and post-3.8 versions.) Set the value to __version__ in sample/__init__.py and import sample in setup.py. Use setuptools_scm to extract versioning from source control so that it's the canonical reference, not code.
注意(7)可能是最现代的方法(构建元数据独立于代码,由自动化发布)。还要注意,如果setup用于包发布,那么简单的python3 setup.py——version将直接报告版本。
在python包中嵌入版本字符串似乎没有标准的方法。我见过的大多数包都使用您的解决方案的一些变体,即eitner
将版本嵌入到setup.py中,并让setup.py生成一个只包含版本信息的模块(例如version.py),该模块由你的包导入,或者 相反:把版本信息放在你的包中,然后在setup.py中导入它来设置版本
我更喜欢从安装环境中读取包版本。 这是我的src/foo/_version.py:
from pkg_resources import get_distribution
__version__ = get_distribution('foo').version
确保foo总是已经安装,这就是为什么需要src/ layer来防止在没有安装的情况下导入foo。
在setup.py中,我使用setuptools-scm自动生成版本。
2022.7.5更新:
还有另一种方法,这是我现在最喜欢的。使用setuptools-scm生成_version.py文件。
setup(
...
use_scm_version={
'write_to':
'src/foo/_version.py',
'write_to_template':
'"""Generated version file."""\n'
'__version__ = "{version}"\n',
},
)
《绿箭侠》以一种有趣的方式处理它。
现在(2e5031b起)
在箭头/ __init__ . py:
__version__ = 'x.y.z'
在setup . py:
from arrow import __version__
setup(
name='arrow',
version=__version__,
# [...]
)
之前
在箭头/ __init__ . py:
__version__ = 'x.y.z'
VERSION = __version__
在setup . py:
def grep(attrname):
pattern = r"{0}\W*=\W*'([^']+)'".format(attrname)
strval, = re.findall(pattern, file_text)
return strval
file_text = read(fpath('arrow/__init__.py'))
setup(
name='arrow',
version=grep('__version__'),
# [...]
)