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

import foo
print(foo.version)

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


当前回答

同样值得注意的是,__version__是一个半std。在python中,__version_info__也是一个元组,在简单的情况下,你可以这样做:

__version__ = '1.2.3'
__version_info__ = tuple([ int(num) for num in __version__.split('.')])

...你可以从文件或其他地方获取__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,因为我可以自动管理元数据。

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

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

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

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

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

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

如果您使用CVS(或RCS)并想要快速解决方案,您可以使用:

__version__ = "$Revision: 1.1 $"[11:-2]
__version_info__ = tuple([int(s) for s in __version__.split(".")])

(当然,修订号会被CVS代替)

这为您提供了一个打印友好的版本和版本信息,您可以使用它来检查您正在导入的模块至少具有预期的版本:

import my_module
assert my_module.__version_info__ >= (1, 1)

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

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

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

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

重写2017 - 05

在写了13年以上的Python代码和管理各种包之后,我得出的结论是,DIY可能不是最好的方法。

我开始使用pbr包来处理包中的版本控制。如果您正在使用git作为您的SCM,这将像魔法一样适合您的工作流,节省您数周的工作时间(您将惊讶于问题的复杂程度)。

截至目前,pbr的月下载量为1200万次,达到这一水平并不需要任何肮脏的手段。这只是一件事——用非常简单的方法解决一个常见的包装问题。

PBR可以承担更多的包维护负担,而且不局限于版本控制,但它不会强迫您采用它的所有好处。

所以为了给你一个关于如何在一次提交中采用策略br的想法,看看切换包装到策略br

您可能会注意到版本根本没有存储在存储库中。PBR确实从Git分支和标记中检测到它。

不需要担心没有git存储库时会发生什么,因为在打包或安装应用程序时,pbr会“编译”并缓存版本,因此不依赖于git的运行时。

旧的解决方案

以下是我迄今为止见过的最好的解决方案,它也解释了为什么:

借“yourpackage / 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__ = '0.12'

内部yourpackage / __init__ . py:

from .version import __version__

在setup . py:

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

如果你知道其他更好的方法,请告诉我。