需求

在写一个程序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. flask 中使用 socket 遇到的坑

    很久没用博客园了,最近涉及到一个问题,需要向前端推送日志 考虑的方案两个,一个是定时ajax 但是这样效率太慢了,二是用socket 那看看有没有轮子咯,面向百度编程,有两个库可以使用 1.flask ...

  2. SpringCloud使用Sofa-lookout监控(基于Eureka)

    本文介绍SpringCloud使用Sofa-lookout,基于Eureka服务发现. 1.前景 本文属于是前几篇文章的后续,其实一开始感觉这个没有什么必要写的,但是最近一个朋友问我关于这个的问题,所 ...

  3. VMware workstation pro 15 安装Ubuntu(图文教程)

    今天分享一下虚拟机安装Ubuntu的过程,在开始安装之前,需要下载VMware workstation pro和Ubuntu镜像,两者我都用的最新版,由于VMware workstation pro ...

  4. Oracle、DB2、SQLSERVER、Mysql、Access分页SQL语句

    最近把平时在项目中常用到的数据库分页sql总结了下.大家可以贴出分页更高效的sql语句.sqlserver分页  第一种分页方法 需用到的参数:  pageSize 每页显示多少条数据  pageNu ...

  5. python学习:continue及break使用

    continue及break使用 #continue 作用:结束本次循环,继续下次循环#break 作用:跳出整个当次循环 for i in range(10): if i < 5: conti ...

  6. 关于分页器border重叠问题

    .paging li { cursor: pointer; display: inline-block; float: left; box-sizing: border-box; margin-lef ...

  7. 详解node + mongoDb(mongoDb安装、运行,在node中连接、增删改查)

    一.序言 好久没写博客了,这次主要聊聊 node 和 mongoDb . 先说明一下技术栈  node + express + mongoose + mongoDb.这篇博客,主要讲述 mongoDb ...

  8. Java课堂笔记(零):内容索引

    回想自己学习和使用Java的时间也是很长了.本科期间课堂上浅尝辄止地学习了点皮毛,后来也是搁置不用,未曾深入研究.研究生期间因为项目和实习的原因,基本算是重新拾起Java这门语言,并且接触到了Spri ...

  9. 树莓派3B+上运行.Net Core项目

    最近买了个树莓派3B+,准备把自己写的一个.Net Core爬虫挂在上面跑 买之前没有想到树莓派因为是今年新出的,导致驱动以及系统啥的都不是很完善,导致走了很多弯路,早知道买树莓派3就不用那么多折腾了 ...

  10. ArcMap AddIn之下载ArcGIS Server地图服务中的数据

    涉及到开发知识点1.ArcGIS Server地图服务 2.C# web请求获取数据 3.AddIN开发技术 工具界面: 具体涉及到的代码之后有空贴出来.先上工具 AddIn插件下载地址:点击这里下载 ...