需求

在写一个程序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. 通过zuul修改请求参数——对请求参数进行解密

    zuul是netflix开源的一个API Gateway 服务器, 本质上是一个web servlet应用,Zuul 在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架,Zuul 相当于是设备和 ...

  2. 图形上下文导论(Introduction to SWT Graphics)zz

    图形上下文导论(Introduction to SWT Graphics) 摘要: org.eclipse.swt.graphics包(package),包含了管理图形资源的类.只要实现了org.ec ...

  3. datatable中的copy和clone的用法区分

    dt.copy();//复制结构和数据 dt.clone();//仅复制结构,不复制数据

  4. VS2017下使用Git遇到的问题

    我在使用最新版的VS2017时,想获取服务器上最新代码,Fetch到了最新修改,但是在拉取代码的时候出现了问题 user@user-PC MINGW64 /d/demo/myrepos (dev-cs ...

  5. 原生JS面试题

    面试中遇到的原生js题总结   1.js 去重1) indexOf Array.prototype.unique = function(){ var result = []; var len = th ...

  6. 在Centos中部署nginx

    准备工作: nginx的安装依赖openSSL,zlib和pcre Openssl下载地址: http://www.openssl.org/ zlib下载地址: http://www.zlib.net ...

  7. [LeetCode] Exam Room 考试房间

    In an exam room, there are N seats in a single row, numbered 0, 1, 2, ..., N-1. When a student enter ...

  8. laravel之url跳转

    1.先写一下路由 2.在写a标签跳转

  9. js数组和对象相等判断、拷贝详解(结合几个现象讲解引用数据类型的趣事)

    序言 最近遇到几个js引用数据类型造成的bug,今天结合bug详细分析一下,避免以后再犯,也希望能帮大家提个醒,强化js基本功. 目录 1.浅拷贝.深拷贝,解决变量赋值相互影响问题 2.判断2个数组. ...

  10. python爬虫第四天

        昨天学到了正则表达式基础知识 :原子 今天开始学习第二个基础知识:元字符 元字符     就是正则表达式中含有特殊含义的一些字符 常见的元字符及含义   符号 含义 . 匹配除换行符以外 的任 ...