将版本嵌入 Python 包的标准方法?

新手上路,请多包涵

是否有一种标准方法可以将版本字符串与 Python 包相关联,以便我可以执行以下操作?

 import foo
print(foo.version)

我想有一些方法可以在没有任何额外硬编码的情况下检索该数据,因为次要/主要字符串已经在 setup.py 中指定。 Alternative solution that I found was to have import __version__ in my foo/__init__.py and then have __version__.py generated by setup.py .

原文由 Dimitri Tcaciuc 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 711
2 个回答

不是直接回答你的问题,但你应该考虑命名它 __version__ ,而不是 version

这几乎是一个准标准。标准库中的很多模块都使用了 __version__ ,这个也用在了 很多 3rd-party 模块中,所以它是准标准。

通常, __version__ 是一个字符串,但有时它也是一个浮点数或元组。

正如 S.Lott(谢谢!)所提到的, PEP 8 明确指出:

模块级 Dunder 名称

模块级别的“dunders”(即带有两个前导和两个尾随下划线的名称),例如 __all__ , __author__ , __version__ 应该放在模块之后文档字符串,但在任何导入语句之前,除了来自 __future__ 导入。

您还应该确保版本号符合 PEP 440PEP 386 是该标准的先前版本)中描述的格式。

原文由 oefe 发布,翻译遵循 CC BY-SA 4.0 许可协议

我使用单个 _version.py 文件作为“曾经规范的地方”来存储版本信息:

  1. 它提供了一个 __version__ 属性。

  2. 它提供标准元数据版本。因此,它将被 pkg_resources 或其他解析包元数据(EGG-INFO 和/或 PKG-INFO,PEP 0345)的工具检测到。

  3. 在构建您的包时,它不会导入您的包(或其他任何东西),这在某些情况下可能会导致问题。 (请参阅下面关于这可能导致什么问题的评论。)

  4. 版本号只有一个地方被记下,所以版本号变化的时候也只有一个地方可以改,版本不一致的几率更小。

它是这样工作的:存储版本号的“一个规范位置”是一个名为“_version.py”的 .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 将该字符串作为“版本”参数的值传递给 setup() ,从而满足功能 2。

为了满足功能 1,您可以让您的包(在运行时,而不是在设置时!)从 myniftyapp/__init__.py 导入 _version 文件,如下所示:

 from _version import __version__

这是我多年来一直使用 的这种技术的一个例子

那个例子中的代码有点复杂,但是我在这个注释中写的简化的例子应该是一个完整的实现。

这是 导入版本的示例代码

如果您发现这种方法有任何问题,请告诉我。

原文由 Zooko 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题