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

import foo
print(foo.version)

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


当前回答

根据延迟的[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()

带有bump2版本的策略路由

这个解决方案来自本文

用例- python GUI包通过PyInstaller分发。需要显示版本信息。

这里是项目包的结构

packagex
├── packagex
│   ├── __init__.py
│   ├── main.py
│   └── _version.py
├── packagex.spec
├── LICENSE
├── README.md
├── .bumpversion.cfg
├── requirements.txt
├── setup.cfg
└── setup.py

setup.py在哪里

# setup.py
import os

import setuptools

about = {}
with open("packagex/_version.py") as f:
    exec(f.read(), about)

os.environ["PBR_VERSION"] = about["__version__"]

setuptools.setup(
    setup_requires=["pbr"],
    pbr=True,
    version=about["__version__"],
)

Packagex /_version.py包含just

__version__ = "0.0.1"

和packagex / __init__ . py

from ._version import __version__

对于.bumpversion.cfg

[bumpversion]
current_version = 0.0.1
commit = False
tag = False
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<release>[a-z]+)(?P<build>\d+))?
serialize = 
    {major}.{minor}.{patch}-{release}{build}
    {major}.{minor}.{patch}

[bumpversion:part:release]
optional_value = prod
first_value = dev
values = 
    dev
    prod

[bumpversion:file:packagex/_version.py]

使用setuptools和pyproject.toml

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

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

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

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

__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__(或任何它将被称为)存储为整数值的元组将允许更有效的版本比较。

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