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

import foo
print(foo.version)

我认为有一些方法可以在没有任何额外硬编码的情况下检索数据,因为minor/major字符串已经在setup.py中指定了。我发现的替代解决方案是在我的foo/__init__.py中导入__version__,然后由setup.py生成__version__.py。


当前回答

无论如何,如果你使用NumPy distutils, NumPy .distutils.misc_util。Configuration有一个make_svn_version_py()方法,它将版本号嵌入到包中。变量version中的__svn_version__。

其他回答

我在包目录中使用了一个JSON文件。这符合Zooko的要求。

内部pkg_dir / pkg_info.json:

{"version": "0.1.0"}

在setup . py:

from distutils.core import setup
import json

with open('pkg_dir/pkg_info.json') as fp:
    _info = json.load(fp)

setup(
    version=_info['version'],
    ...
    )

内部pkg_dir / __init__ . py:

import json
from os.path import dirname

with open(dirname(__file__) + '/pkg_info.json') as fp:
    _info = json.load(fp)

__version__ = _info['version']

我还在pkg_info中放入了其他信息。Json,比如author。我 我喜欢使用JSON,因为我可以自动管理元数据。

在与__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__。

我使用一个单独的_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__

这是我多年来一直在使用的一个技巧的例子。

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

下面是导入版本的示例代码。

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

我在这里描述了一种标准的现代方法,它依赖于setuptools_scm。 在过去的几年中,这种模式已经成功地应用于许多已发布的包,因此我强烈推荐它。

注意,您不需要getversion包来实现这个模式。getversion文档恰好包含这个技巧。