【问题标题】:Python version number comparison with != (not equal)Python 版本号与 != 比较(不等于)
【发布时间】:2021-08-04 06:01:19
【问题描述】:

我正在尝试编写一个从setup.py 复制python_requires 行为的函数,因为我未能在setuptools 和pip 的源代码中找到实现。比较 Python should be easy enough 中的版本号,我使用的是 packaging.version,它为我完成了所有工作,除了...

让我们看看像">=2.6, !=3.0.*, !=3.1.*" 这样的版本字符串。我在每个逗号处分开,然后分别查看每个比较:

from packaging import version
version.parse("3.0.5") >= version.parse("2.6")

正如预期的那样,3.0.5 版本高于 2.6。下一个:

version.parse("3.0.5") != version.parse("3.0.*")

这将返回 True(即3.0.53.0.* 不同),但版本3.0.5 实际上应该匹配3.0.*。 Python中是否有标准方法来检查带有通配符的版本号是否与另一个版本号匹配?

edit:也相关,我将如何实现兼容的版本匹配器,例如~= 3.0.5,它应该匹配任何版本>= 3.0.5< 3.1.0

看来我正在尝试在这里实现PEP 440 的版本说明符...

【问题讨论】:

    标签: python versioning semantic-versioning


    【解决方案1】:

    根据the documentation packaging.version.parse 仅用于解析PEP 440 兼容的版本号,其中"3.0.*" 不是其中之一。通配符的使用在 PEP 中被称为在匹配时有效,但它们实际上并不是版本方案的一部分。

    packaging.version.parse 被赋予一个不兼容的版本号来解析时,它会以packaging.version.LegacyVersion 而不是packaging.version.Version 的形式返回。您可以确认这就是您的案件退回的内容。据推测,操作员在这些方面的工作方式不同(可能根本没有实现),他们在设置工具中实现了一些额外的逻辑来处理LegacyVersion 对象。

    【讨论】:

    • 你知道这是如何在 setuptools 或 pip 中实现的吗?对于同时支持 Python 2 和 3 的包来说,将 python_requires 定义为 ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 似乎相当普遍
    • @klamann 不幸的是,我没有。我对内部不太熟悉,只是文档。
    【解决方案2】:

    如果您的最终目标只是将版本兼容性与 PEP 440 版本说明符进行比较,看起来packaging.specifiers 已经支持此:

    >>> from packaging.specifiers import SpecifierSet
    >>> vspec = SpecifierSet(">=11.3,!=11.3.2")
    >>> "11.3.1" in vspec
    True
    >>> "11.3.2" in vspec
    False
    >>> 
    

    如果您真的要自己实现,specifiers.py source 可能会有所帮助。看起来一般的方法是对每个运算符进行正则表达式匹配,将它们映射到适当的 Specifier 方法,其中比较在任何特殊处理后推迟到 Version 运算符(例如,_compare_equal() 处理您的“.*”情况询问)。

    【讨论】:

    • 这正是我一直在寻找的,非常感谢!它甚至适用于*~ 以及所有内容:)
    猜你喜欢
    • 2010-12-15
    • 2023-03-20
    • 2023-04-10
    • 2013-09-06
    • 2016-04-24
    相关资源
    最近更新 更多