是否有一种标准的方法将版本字符串与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。
当前回答
不是直接回答你的问题,但你应该考虑将其命名为__version__,而不是version。
这几乎是一个准标准。标准库中的许多模块使用__version__,这也在许多第三方模块中使用,因此它是准标准的。
通常,__version__是一个字符串,但有时它也是一个浮点数或元组。
正如S.Lott所提到的(谢谢!),PEP 8明确表示:
模块级别Dunder名称 模块级别的“dunders”(即名称有两个前导和两个后导 下划线),例如__all__, __author__, __version__等。 应该放在模块文档字符串之后,但在任何导入之前 除了__future__导入之外的语句。
您还应该确保版本号符合PEP 440 (PEP 386是此标准的以前版本)中描述的格式。
其他回答
我使用一个单独的_version.py文件作为“曾经正确的位置”来存储版本信息:
It provides a __version__ attribute. It provides the standard metadata version. Therefore it will be detected by pkg_resources or other tools that parse the package metadata (EGG-INFO and/or PKG-INFO, PEP 0345). It doesn't import your package (or anything else) when building your package, which can cause problems in some situations. (See the comments below about what problems this can cause.) There is only one place that the version number is written down, so there is only one place to change it when the version number changes, and there is less chance of inconsistent versions.
它是这样工作的:存储版本号的“一个规范的地方”是一个.py文件,名为“_version.py”,它在你的Python包中,例如在myniftyapp/_version.py中。这个文件是一个Python模块,但是你的setup.py没有导入它!(这将击败功能3。)相反,你的setup.py知道这个文件的内容非常简单,就像:
__version__ = "3.6.5"
所以你的setup.py打开文件并解析它,代码如下:
import re
VERSIONFILE="myniftyapp/_version.py"
verstrline = open(VERSIONFILE, "rt").read()
VSRE = r"^__version__ = ['\"]([^'\"]*)['\"]"
mo = re.search(VSRE, verstrline, re.M)
if mo:
verstr = mo.group(1)
else:
raise RuntimeError("Unable to find version string in %s." % (VERSIONFILE,))
然后你的setup.py将这个字符串作为"version"参数的值传递给setup(),这样就满足了特性2。
为了满足特性1,你可以让你的包(在运行时,而不是在设置时!)像这样从myniftyapp/__init__.py导入_version文件:
from _version import __version__
这是我多年来一直在使用的一个技巧的例子。
这个例子中的代码有点复杂,但是我写在这个注释中的简化的例子应该是一个完整的实现。
下面是导入版本的示例代码。
如果你发现这种方法有任何问题,请告诉我。
在python包中嵌入版本字符串似乎没有标准的方法。我见过的大多数包都使用您的解决方案的一些变体,即eitner
将版本嵌入到setup.py中,并让setup.py生成一个只包含版本信息的模块(例如version.py),该模块由你的包导入,或者 相反:把版本信息放在你的包中,然后在setup.py中导入它来设置版本
在与__init__.py相同的文件夹中创建一个名为_version.txt的文件,并将version写成一行:
0.8.2
从__init__.py中的_version.txt文件中读取以下信息:
import os
def get_version():
with open(os.path.join(os.path.abspath(os.path.dirname(__file__)), "_version.txt")) as f:
return f.read().strip()
__version__ = get_version()
无论如何,如果你使用NumPy distutils, NumPy .distutils.misc_util。Configuration有一个make_svn_version_py()方法,它将版本号嵌入到包中。变量version中的__svn_version__。
我还看到了另一种风格:
>>> django.VERSION
(1, 1, 0, 'final', 0)