需求

在写一个程序Django项目的setup程序(初始化环境,比如设置PIP源,安装该项目依赖的各种模块等操作)遇到一个系统当前模块版本和项目所需版本的比较然后给出建议是忽略还是升级。我的要求是不仅仅比较版本号是否一致以及返回最大版本号,而且还要给出建议是升级(当前系统包的版本号小于项目需要的版本号)还是忽略(当前系统包的版本号大于等于项目需要的版本号)。下图就是我们要去比较的东西。

解题分析

  • 版本号虽然是数字组成但是一个整体的版本号无法通过数字进行比较需要拆解逐位比较
  • 版本号有长度的区别我们可以称作位,比如1.1.1这就是3位,我们这里的位说的是“.”分割的位数。 1.111.1也是三位。位数就是“.”的个数加1.

算法一:补位算法

比如1.11.2和1.9比较,既然是逐位比较那就需要循环,两个版本号位数不同如果按照最长的位数循环那短的哪一个肯定抛异常,那么我就可以通过补位来实现,怎么补呢?1.9 和 1.9.0 看到了么,这两个版本号是相同的,为什么呢?有谁见过1位的版本号呢?都使用1.0而不会单纯使用1,长度相同那剩下的就是循环比较。

#!/usr/bin/env python
# -*- coding: utf-8 -*- import sys def checkVersion(currentversion, expectedversion):
"""
检查版本号是否相同,当前版本小于期望版本则进行升级,大于等于则忽略。
CODE有两种,88和99 表示建议,88表示当前版本大于等于期待的版本忽略,99表示小于期待版本要进行升级。
:param currentversion: 当前系统存在的版本号
:param expectedversion: 期望的版本号
:return: CODE, MAX_VERSION
""" MAX_VERSION = "0.0.0"
CODE = 88 # 如果两者一样就直接返回,用于加快处理速度。 这里不要用 is 要用 == 来比较内容是否一致。
if expectedversion == currentversion:
CODE = 88
MAX_VERSION = expectedversion
return CODE, MAX_VERSION # 切割成列表
currentversionBITS = currentversion.split(".")
expectedversionBITS = expectedversion.split(".") """
为了避免版本号长度不同比如 1.0.8和1.2 我们把版本号要补全都变成相同长度,比如 1.2.0 这样比较的时候循环次数相同
"""
if len(currentversionBITS) >= len(expectedversionBITS):
amount = len(currentversionBITS) - len(expectedversionBITS)
for i in range(amount):
expectedversionBITS.append("")
else:
amount = len(expectedversionBITS) - len(currentversionBITS)
for i in range(amount):
currentversionBITS.append("") """
逐位比较版本大小,为什么这里采用currentversionBITS的长度来循环呢,其实讲过上面的if语句后无论是currentversionBITS还是expectedversionBITS
位数都相同,这里采用那个长度来控制循环都可以。
"""
for i in range(len(currentversionBITS)):
try:
if int(currentversionBITS[i]) > int(expectedversionBITS[i]):
CODE = 88
MAX_VERSION = currentversion
return CODE, MAX_VERSION
elif int(currentversionBITS[i]) < int(expectedversionBITS[i]):
CODE = 99
MAX_VERSION = expectedversion
return CODE, MAX_VERSION
else:
CODE = 88
MAX_VERSION = expectedversion
except IndexError as err:
pass return CODE, MAX_VERSION def main():
print checkVersion("1.0", "1.1") # 正确的返回 99 1.1
print checkVersion("1.1.2", "1.1") # 正确的返回 88 1.1.2
print checkVersion("1.11.3", "1.11.24") # 正确的返回 99 1.11.24
print checkVersion("1.0.11.3", "1.0.11.2") # 正确的返回 88 1.0.11.3 if __name__ == "__main__":
try:
main()
finally:
sys.exit()

执行结果

算法二:不补位按最小长度循环

不补位就要安装最小位数长度循环,否则就会抛出异常,当然我们可以做异常处理,不过执行逻辑还是不要放在异常里因为异常会影响性能,再说明明这个异常可以避免干嘛还要让它出现呢。

#!/usr/bin/env python
# -*- coding: utf-8 -*- import sys def checkVersionG2(currentversion, expectedversion):
"""
检查版本号是否相同,当前版本小于期望版本则进行升级,大于等于则忽略.本方法是基于第一种方法的改进,性能更好,代码更少。
CODE有两种,88和99 表示建议,88表示当前版本大于等于期待的版本忽略,99表示小于期待版本要进行升级。
:param currentversion: 当前系统存在的版本号
:param expectedversion: 期望的版本号
:return: CODE, MAX_VERSION
""" MAX_VERSION = "0.0.0" # 切割成列表
currentversionBITS = currentversion.split(".")
expectedversionBITS = expectedversion.split(".") """
找出2个版本号位数最小的一个,注意这里就存在数据互换问题,经过这个if语句之后,你就完全不知道 minbitversion和maxbitversion
分别对应的是currentversion还是expectedversion.
"""
if len(currentversionBITS) >= len(expectedversionBITS):
minbitversion = expectedversionBITS
maxbitversion = currentversionBITS
else:
minbitversion = currentversionBITS
maxbitversion = expectedversionBITS """
逐位比较版本大小,按最小位循环,这个循环之后将会找出版本号最大的,而且这里必须让这个循环完成。这里和之前的算法不同。
再多说一句,这里你也可以按照最大位循环,但是你就需要考虑异常,从程序性能角度来说尽量不要使用异常控制逻辑,除非没有更好的选择。
"""
for index, bit in enumerate(minbitversion):
try:
if int(bit) > int(maxbitversion[index]):
MAX_VERSION = ".".join(minbitversion)
break
elif int(bit) < int(maxbitversion[index]):
MAX_VERSION = ".".join(maxbitversion)
break
else:
MAX_VERSION = ".".join(maxbitversion)
except IndexError as err:
pass # 这里则用于找到当前的 MAX_VERSION 到底是currentversion还是expectedversion,只有找到了才能给出建议是忽略还是升级。
# 之前那种算法里没有,因为通过位数补全之后比较不存在一段数据不清状态。
if MAX_VERSION == currentversion:
CODE = 88
else:
CODE = 99 return CODE, MAX_VERSION def main():
print checkVersionG2("1.0", "1.1") # 正确的返回 99 1.1
print checkVersionG2("1.1.2", "1.1") # 正确的返回 88 1.1.2
print checkVersionG2("1.11.3", "1.11.24") # 正确的返回 99 1.11.24
print checkVersionG2("1.0.11.3", "1.0.11.2") # 正确的返回 88 1.0.11.3 if __name__ == "__main__":
try:
main()
finally:
sys.exit()

执行结果

总结

上面只是用了Python的实现,算法通用。这两个方法里面没有对版本号格式的检验简易增加,通过正则就可以。

如何比较版本号--Python实现的更多相关文章

  1. 【从0開始Tornado建站】0.9版本号python站点代码开源--持续更新中

            从5月份開始[从0開始Tornado建站]这个专栏,開始一点一点把这个分类兴趣站点弄起来,从无到有的过程也是令人兴奋的:-) 国庆的时候等待备案然后上线,如今站点域名为ustchack ...

  2. linux查看python安装路径,版本号

    一.想要查看ubuntu中安装的Python路径 方法一:whereis python 方法二:which python 二.想要查看ubuntu中安装的python版本号 python

  3. Redhat Linux下的python版本号升级

    运行#Python与#python -V,看到版本是2.4.3,非常老了,并且之前写的都是跑在python3.X上面的,3.X和2.X有非常多不同, 有兴趣的朋友能够參考下这篇文章:  http:// ...

  4. linux 查看python安装路径,版本号

    一.想要查看ubuntu中安装的python路径 方法一:whereis python     方法二:which python   二.想要查看ubuntu中安装的python版本号 python ...

  5. Python 获得程序 exe 的版本号

    Python 获得程序 exe 的版本号 python中需要安装 pywin32 包 # based on http://stackoverflow.com/questions/580924/pyth ...

  6. python grammar、C/C++ Python Parsing Engine

    catalog . Python语言简介 . Python模块 . 嵌入式Python解析引擎: C++调用Python . Python 调用 C (base) . 扩展Python语法解析器功能: ...

  7. [Python 学习] 两、在Linux使用平台Python

    在本节,它介绍了Linux如何使用平台Python 1. Python安装. 今天,大多数把自己的版本号Python的,它不能被安装.假设你要安装它,可以使用相应的安装指令. Fedora:先以roo ...

  8. python开发部署时新增数据库中表的方法

    在项目版本让运维部署时,涉及到数据库表的增加问题,想了一下,可以有四种方法 1.使用SQLAlchemy的db.create_all()方法 # -*- coding:utf-8 -*- from f ...

  9. 腾讯云python网站开发环境搭建

    前段时间腾讯云做活动,于是就花了几百大洋买了三年的云服务,准备在上 面安装python web的开发环境,下面将安装过程做一个总结,希望能够帮助大家. 一.使用环境   使用的软件环境为:CentOS ...

随机推荐

  1. 【Vue-Cli3.0】【1】创建一个Vue-Cli3.0的项目

    最近在做爬虫,然后要爬好多数据,代码写完了,就让它在爬了.不想闲着就复习一下Vue吧! 开始开始! ***正式讲解之前 先下载一个node.js吧! 一.首先检查一下 版本 PS D:\徐孟林\D D ...

  2. BZOJ5326 : [Jsoi2017]博弈

    将所有物品按照$b$的选择顺序排序,则先手在任意前$i$个物品中最多只能拿走$\lceil\frac{i}{2}\rceil$个物品. 将每个物品的价值设为$a+b$,那么答案为先手拿走的价值和减去所 ...

  3. 微信JS SDK接入的几点注意事项

    微信JS SDK接入,主要可以先参考官网说明文档,总结起来有几个步骤: 1.绑定域名:先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.备注:登录后可在“开发者中心”查看对 ...

  4. 常用的Tensor操作

    常用的Tensor操作 1.通过tensor.view方法可以调整tensor的形状,但必须保证调整去前后元素总数一致.view不会修改自身的数据,返回新的tensor与原tensor共享内存,即更改 ...

  5. vue 格式化银行卡(信用卡)每4位一个符号隔断

    问题 在做银行卡输入框时有一个需求如题,这里举例用-隔断 调查 查看了很多大公司网站的银行卡输入,发现还有有很多缺陷的: 有的是在中间删除,光标会跳到最后: 有的是能删除掉中间隔断符的: 等等,逻辑感 ...

  6. 我和python的初相识

    认识Python是大二的选修 单纯只是想赚学分而已 后来觉得越来越有趣. 一.python简介 简单来说Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言.Python 的设 ...

  7. Java_异常处理

    这篇我们聊聊java中的异常.首先我们要知道什么是异常? Exception: exception翻译过来就是“意外”的意思.事实上,异常的本质就是程序的错误,包括程序逻辑错误和系统错误.错误在编写程 ...

  8. 在vue中使用sass的配置的方法

    1.安装sass的依赖包 npm install --save-dev sass-loader //sass-loader依赖于node-sass npm install --save-dev nod ...

  9. js 压缩

    听到同事说没找到压缩js文件的,说软件压缩貌似有点问题,我自己就用nodejs练手般写了压缩文件的. 主要的思路就是,先通过前端上传js文件,然后服务器接收,然后引用uglifyjs 压缩,再返回文件 ...

  10. 【数据结构】红黑树与跳表-(SortSet)-(TreeMap)-(TreeSet)

    SortSet 有序的Set,其实在Java中TreeSet是SortSet的唯一实现类,内部通过TreeMap实现的:而TreeMap是通过红黑树实现的:而在Redis中是通过跳表实现的: Skip ...