我正在浏览一个包含卵的目录,以便将这些卵添加到sys.path。如果目录中有相同的.egg的两个版本,我只想添加最新的版本。
我有一个正则表达式r ^ (? P < eggName > \ w +) - (? P < eggVersion > (\ d \.]+)-.+\.Egg $从文件名中提取名称和版本。问题是比较版本号,它是一个像2.3.1这样的字符串。
因为我比较字符串,2排序超过10,但这是不正确的版本。
>>> "2.3.1" > "10.1.1"
True
我可以做一些拆分、解析、转换为int等,最终我将得到一个变通方法。但这是Python,不是Java。是否有一种优雅的方法来比较版本字符串?
有包装包可用,这将允许您比较版本按照PEP-440,以及遗留版本。
>>> from packaging.version import Version, LegacyVersion
>>> Version('1.1') < Version('1.2')
True
>>> Version('1.2.dev4+deadbeef') < Version('1.2')
True
>>> Version('1.2.8.5') <= Version('1.2')
False
>>> Version('1.2.8.5') <= Version('1.2.8.6')
True
旧版本支持:
>>> LegacyVersion('1.2.8.5-5-gdeadbeef')
<LegacyVersion('1.2.8.5-5-gdeadbeef')>
比较遗留版本和PEP-440版本。
>>> LegacyVersion('1.2.8.5-5-gdeadbeef') < Version('1.2.8.6')
True
基于Kindall的解决方案发布我的完整功能。通过用前导零填充每个版本部分,我能够支持混合在数字中的任何字母数字字符。
虽然肯定不如他的一行函数漂亮,但它似乎可以很好地处理字母数字版本号。(如果您的版本控制系统中有较长的字符串,请确保适当地设置zfill(#)值。)
def versiontuple(v):
filled = []
for point in v.split("."):
filled.append(point.zfill(8))
return tuple(filled)
.
>>> versiontuple("10a.4.5.23-alpha") > versiontuple("2a.4.5.23-alpha")
True
>>> "10a.4.5.23-alpha" > "2a.4.5.23-alpha"
False
打包库包含用于处理版本和其他打包相关功能的实用程序。它实现了PEP 0440——版本标识,还能够解析不遵循PEP的版本。pip和其他常用的Python工具使用它来提供版本解析和比较。
$ pip install packaging
from packaging.version import parse as parse_version
version = parse_version('1.0.3.dev')
它从setuptools和pkg_resources中的原始代码中分离出来,以提供更轻量级和更快的包。
在打包库存在之前,这个功能在pkg_resources (setuptools提供的一个包)中可以找到(现在仍然可以找到)。然而,这不再是首选,因为setuptools不再保证被安装(存在其他打包工具),具有讽刺意味的是,pkg_resources在导入时使用了相当多的资源。然而,所有的文档和讨论仍然是相关的。
从parse_version()文档:
解析由PEP 440定义的项目版本字符串。返回值将是一个表示版本的对象。这些对象可以相互比较和排序。排序算法是由PEP 440定义的,添加的是,任何不是有效PEP 440版本的版本都将被视为小于任何有效PEP 440版本,无效版本将继续使用原始算法进行排序。
引用的“原始算法”是在PEP 440存在之前的旧版本文档中定义的。
从语义上讲,该格式是distutils的StrictVersion类和LooseVersion类之间的一个粗略的交叉;如果你给它一个与StrictVersion兼容的版本,那么它们会以同样的方式进行比较。否则,比较更像是一种“更聪明”的LooseVersion形式。可以创建病态的版本编码方案来欺骗这个解析器,但在实践中应该非常罕见。
文档提供了一些例子:
如果你想确定你选择的编号方案是否有效
您可以使用pkg_resources.parse_version()
函数比较不同版本号:
>>>从pkg_resources导入parse_version
> > > parse_version (1.9.a.dev) = = parse_version(“1.9 a0dev”)
真正的
> > > parse_version (2.1 rc2) < parse_version(“2.1”)
真正的
>>> parse_version('0.6a9dev-r41475') < parse_version('0.6a9')
真正的