python排序自定义版本号
1.LooseVersion版本排序
1.1 格式
# 合法格式
re.compile(r'(\d+ | [a-z]+ | \.)', re.VERBOSE)
1.2 成功
from distutils.version import LooseVersion
version_list = ['1.1.2', '1.1.3-rc1', '1.1.2-rc3', '1.1.2-rc1', '1.1.3']
version_list.sort(key=LooseVersion, reverse=True)
print(version_list)
['1.1.3-rc1', '1.1.3', '1.1.2-rc3', '1.1.2-rc1', '1.1.2']
1.3 报错
from distutils.version import LooseVersion
version_list = ['1.1.2', '1.1.3-rc1', '1.1.2-rc3', '1.1.2-rc1', '1.1.3', '1.1.2.1']
version_list.sort(key=LooseVersion, reverse=True)
print(version_list)
TypeError: '<' not supported between instances of 'str' and 'int'
2.StrictVersion版本排序
2.1 格式
# 合法格式
re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$',re.VERBOSE | re.ASCII)
2.2 成功
from distutils.version import StrictVersion
version_list = ['1.1.2a1','1.1.2a2', '1.1.2b1', '1.1.3', '1.1.1', '1.1.2']
version_list.sort(key=StrictVersion, reverse=True)
print(version_list)
['1.1.3', '1.1.2', '1.1.2b1', '1.1.2a2', '1.1.2a1', '1.1.1']
2.3 报错
from distutils.version import StrictVersion
version_list = ['1.1.2', '1.1.3-rc1', '1.1.2-rc3', '1.1.2-rc1', '1.1.3']
version_list.sort(key=StrictVersion, reverse=True)
print(version_list)
ValueError: invalid version number '1.1.3-rc1'
3.自定义MyVersion版本排序
1.1.1.1
>1.1.1
>1.1.1-rc1
3.1 格式
# 合法格式
1.1.1 # 正式版本
1.1.1-rc1 # 预发布版本
1.1.1.1 # 紧急修复版本
3.2 自定义排序
from distutils.version import Version
# 复制StrictVersion,并修改
class MyVersion(Version):
# 正则获取版本中的数字(更改)
version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)((-rc|\.)(\d+))?', re.VERBOSE | re.ASCII)
def parse(self, vstring):
match = self.version_re.match(vstring)
# 重写判断逻辑(更改)
if match:
(major, minor, patch, prerelease, prerelease_num) = match.group(1, 2, 3, 5, 6)
if patch:
self.version = tuple(map(int, [major, minor, patch]))
else:
self.version = tuple(map(int, [major, minor], 0))
if prerelease == '.':
self.prerelease = (int(prerelease_num), 10000)
elif prerelease == '-rc':
self.prerelease = (0, int(prerelease_num))
else:
self.prerelease = (1, 0)
else:
self.version = tuple(map(int, [0, 0, 0]))
self.prerelease = (0, 0)
# 这个是打印信息时候看的内容(更改)
def __str__(self):
return str(self.version + self.prerelease)
def _cmp(self, other):
if isinstance(other, str):
# 换成自定义的MyVersion(更改)
other = MyVersion(other)
if self.version != other.version:
if self.version < other.version:
return -1
else:
return 1
if (not self.prerelease and not other.prerelease):
return 0
elif (self.prerelease and not other.prerelease):
return -1
elif (not self.prerelease and other.prerelease):
return 1
elif (self.prerelease and other.prerelease):
if self.prerelease == other.prerelease:
return 0
elif self.prerelease < other.prerelease:
return -1
else:
return 1
else:
assert False, "never get here"
3.3 测试自定义排序
import re
from myversion import MyVersion
version_list = ['1.1.2', '1.1.3-rc1', '1.1.2-rc3', '1.1.2-rc1', '1.1.3']
version_list.sort(key=MyVersion, reverse=True)
print(version_list)
['1.1.3', '1.1.3-rc1', '1.1.2', '1.1.2-rc3', '1.1.2-rc1']
4.原理
把所有数字提取出来放入元组中比对
4.1 根据元组比对
print((1, 0, 1) < (1, 1)) # 1.0.1 < 1.1.0
print((1, 0, 1) < (1, 1, 3)) # 1.0.1 < 1.1.3
print((1, 1, 'a', 1) < (1, 1, 'b', 1)) # 1.1.a.1 < 1.1.b.1
True
True
True
4.2 StrictVersion原理
# 设置前3位数字进行大版本号判断
self.version = tuple(map(int, [major, minor, patch]))
# 设置后2两位进行小版本判断
self.prerelease = (prerelease[0], int(prerelease_num))
# 比较【1.1.1a1】和【1.1.1b1】大小
# 版本拆分【1.1.1a1】
version = (1,1,1)
prerelease = ('a',1)
# 版本拆分【1.1.1b1】
version = (1,1,1)
prerelease = ('b',1)
# 先判断大版本号是否相同(可以判断出直接返回)
if self.version != other.version:
# numeric versions don't match
# prerelease stuff doesn't matter
if self.version < other.version:
return -1
else:
return 1
# 大版本相同,进行小版本对比
if (not self.prerelease and not other.prerelease):
return 0
elif (self.prerelease and not other.prerelease):
return -1
elif (not self.prerelease and other.prerelease):
return 1
elif (self.prerelease and other.prerelease):
if self.prerelease == other.prerelease:
return 0
elif self.prerelease < other.prerelease:
return -1
else:
return 1
else:
assert False, "never get here"
4.3 re匹配
匹配取值
(匹配1)(匹配2)(匹配3) (匹配4(匹配5)(匹配6))
, 匹配4包含了5和6
匹配修复版本号
import re
version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)((-rc|\.)(\d+))?', re.VERBOSE | re.ASCII)
m1 = version_re.match('1.3.2.1')
print(m1.groups())
print(m1.group(1, 2, 3, 5, 6))
('1', '3', '2', '.1', '.', '1')
('1', '3', '2', '.', '1')
匹配正式版本号
import re
version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)((-rc|\.)(\d+))?', re.VERBOSE | re.ASCII)
m2 = version_re.match('1.3.2')
print(m2.groups())
print(m2.group(1, 2, 3, 5, 6))
('1', '3', '2', None, None, None)
('1', '3', '2', None, None)
匹配rc版本号
import re
version_re = re.compile(r'^(\d+)\.(\d+)\.(\d+)((-rc|\.)(\d+))?', re.VERBOSE | re.ASCII)
m3 = version_re.match('1.3.2-rc1')
print(m3.groups())
print(m3.group(1, 2, 3, 5, 6))
('1', '3', '2', '-rc1', '-rc', '1')
('1', '3', '2', '-rc', '1')