存在 pyproject.toml 的 Python 项目版本的单一事实来源

use*_*717 11 python version pyproject.toml

pyproject.toml 规范提供了指定项目版本的能力,例如

[project]
name = "foo"
version = "0.0.1"
Run Code Online (Sandbox Code Playgroud)

然而,它也是一个常见的 Python 习惯用法,可以__version__ = "0.0.1"放入foo/__init__.py以便用户查询。

是否有一种标准方法可以version从 中提取pyproject.toml并将其放入 中foo/__init__.py

wim*_*wim 16

您可以在此处采取两种方法。

  1. 保留版本pyproject.toml并从源代码中的包元数据中获取它。因此,在您mypkg/__init__.py或任何地方:

    from importlib.metadata import version
    __version__ = version("mypkg")
    
    Run Code Online (Sandbox Code Playgroud)

    importlib.metadata.version自 Python 3.8 起可用。对于早期的 Python 版本,您可以使用importlib_metadata向后移植进行类似的操作。

  2. 将版本保留在源代码中并指示构建系统从那里获取它。对于 setuptools 构建后端,它看起来像这样pyproject.toml

    [project]
    name = "mypkg"
    dynamic = ["version"]
    
    [tool.setuptools.dynamic]
    version = {attr = "mypkg.__version__"}
    
    Run Code Online (Sandbox Code Playgroud)

我的建议是()...两者都不是__version__根本不要在源代码中保留属性。这是一个过时的习惯,现在我们可以不用了。Version已经是包元数据中的必填字段,因此在包/模块命名空间中保留与属性相同的字符串是多余的。

  • 用户将按照第 1 点中演示的相同方式执行此操作:通过调用 `version("yourpackage")`。正如你在问题中所说,这个属性只是一个“常见的Python习惯用法”,所以它不像`module.__version__`一般来说是可靠的(它可能存在也可能不存在)。获取元数据版本_是_可靠的,因为它保证存在于已安装的软件包中(参考[_PEP 566 – Python 软件包2.1 的元数据_](https://peps.python.org/pep-0566/))。 (3认同)
  • 如果您已经在以前的版本中提供了 __version__` 属性,并且需要保留向后兼容性,请选择 1. 或 2.,但对于新项目,我认为最好不要将 `__version__` 属性放在第一名。 (2认同)