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

import foo
print(foo.version)

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


当前回答

经过几个小时的努力,我找到了最简单可靠的解决方案,以下是其中的几个部分:

在你的包"/mypackage"文件夹中创建一个version.py文件:

# Store the version here so:
# 1) we don't load dependencies by storing it in __init__.py
# 2) we can import it in setup.py for the same reason
# 3) we can import it into your module module
__version__ = '1.2.7'

在setup . py:

exec(open('mypackage/version.py').read())
setup(
    name='mypackage',
    version=__version__,

在主文件夹init.py中:

from .version import __version__

exec()函数在任何导入之外运行脚本,因为在导入模块之前运行setup.py。您仍然只需要在一个地方的一个文件中管理版本号,但不幸的是,它不在setup.py中。(这是缺点,但没有导入错误是优点)

其他回答

《绿箭侠》以一种有趣的方式处理它。

现在(2e5031b起)

在箭头/ __init__ . py:

__version__ = 'x.y.z'

在setup . py:

from arrow import __version__

setup(
    name='arrow',
    version=__version__,
    # [...]
)

之前

在箭头/ __init__ . py:

__version__ = 'x.y.z'
VERSION = __version__

在setup . py:

def grep(attrname):
    pattern = r"{0}\W*=\W*'([^']+)'".format(attrname)
    strval, = re.findall(pattern, file_text)
    return strval

file_text = read(fpath('arrow/__init__.py'))

setup(
    name='arrow',
    version=grep('__version__'),
    # [...]
)

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

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

根据延迟的[STOP PRESS: rejected] PEP 396(模块版本号),有一种建议的方法来做到这一点。它描述了模块遵循的基本原理(当然是可选的)标准。下面是一个片段:

当模块(或包)包含版本号时,该版本应该在__version__属性中可用。

对于位于命名空间包中的模块,模块应该包含__version__属性。命名空间包本身不应该包含自己的__version__属性。

__version__属性的值应该是一个字符串。

在与__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()

使用setuptools和pyproject.toml

Setuptools现在提供了一种动态获取pyproject.toml版本的方法

重现这里的示例,您可以在pyproject.toml中创建如下内容

# ...
[project]
name = "my_package"
dynamic = ["version"]
# ...
[tool.setuptools.dynamic]
version = {attr = "my_package.__version__"}