你真的需要/想要一个__version__
属性吗?
保持一个__version__
模块命名空间中可用的属性是一种流行的约定,但它可能这些天不再流行了 https://peps.python.org/pep-0396/#pep-rejection因为标准库importlib.metadata https://docs.python.org/3/library/importlib.metadata.html#distribution-versions不再是临时的。版本字符串的一个明显位置是在包元数据中,在模块属性中重复相同的信息可能被认为是不必要和多余的。
当版本字符串存在于两个不同的位置时,它还为用户带来了一些难题 - 我们应该首先在包元数据中还是在模块顶级命名空间中查找它?如果在这些地方找到的版本信息是,我们应该相信哪一个?不同的?
因此,仅将其存储在一个位置有一些好处,并且该位置必须是包的元数据。这是因为Version
字段是一个required领域中的核心元数据规范 https://packaging.python.org/en/latest/specifications/core-metadata/,但是选择提供的软件包__version__
属性只是遵循约定。
获取/设置包元数据中的版本
如果您使用的是现代构建系统,那么您可以直接在中指定版本字符串pyproject.toml
如中所述PEP 621 - 在 pyproject.toml 中存储项目元数据 https://peps.python.org/pep-0621/#version。问题中已经显示的方式是正确的:
[project]
name = "mypkg"
version = "0.0.1"
用户mypkg
可以像这样检索版本:
from importlib.metadata import version
version("mypkg")
请注意,与访问__version__
属性,此版本仅从包元数据中检索,甚至不需要导入实际的包。这在某些情况下很有用,例如具有导入副作用(例如 numpy)的包,或者即使具有不满足的依赖项/复杂的环境设置要求也能够检索包版本的包。
如果您想访问包本身的版本号怎么办?
有时这很有用,例如添加--version
命令行界面的选项。但这并不意味着您需要__version__
属性闲逛时,您可以以相同的方式从您自己的包元数据中检索版本:
parser = argparse.ArgumentParser(...)
...
parser.add_argument(
"--version",
action="version",
version=importlib.metadata.version("mypkg"),
)