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

import foo
print(foo.version)

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


当前回答

与其他一些答案相比,还有一个稍微简单一点的选择:

__version_info__ = ('1', '2', '3')
__version__ = '.'.join(__version_info__)

(使用str()将版本号的自动递增部分转换为字符串相当简单。)

Of course, from what I've seen, people tend to use something like the previously-mentioned version when using __version_info__, and as such store it as a tuple of ints; however, I don't quite see the point in doing so, as I doubt there are situations where you would perform mathematical operations such as addition and subtraction on portions of version numbers for any purpose besides curiosity or auto-incrementation (and even then, int() and str() can be used fairly easily). (On the other hand, there is the possibility of someone else's code expecting a numerical tuple rather than a string tuple and thus failing.)

当然,这是我自己的观点,我很乐意听取其他人对使用数字元组的意见。


正如shezi提醒我的那样,(词汇)数字串的比较并不一定与直接的数字比较有相同的结果;需要前导零来提供这一点。因此,最后,将__version_info__(或任何它将被称为)存储为整数值的元组将允许更有效的版本比较。

其他回答

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

现在(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__'),
    # [...]
)

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

这几乎是一个准标准。标准库中的许多模块使用__version__,这也在许多第三方模块中使用,因此它是准标准的。

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

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

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

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

我还看到了另一种风格:

>>> django.VERSION
(1, 1, 0, 'final', 0)

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

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

我在包目录中使用了一个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,因为我可以自动管理元数据。