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')
posted @ 2023-03-23 14:56  lxd670  阅读(120)  评论(0编辑  收藏  举报