需求

在写一个程序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. django自制后台左侧导航代码

    自定义一个sort.py页面: 写入一下代码: class lanmusort(object): def __init__(self): self.arr=[] def lanmuget(self,o ...

  2. ISP PIPLINE (十五) AF

    主流的AF: CDAF, PDAF, laser assist AF(这个只是辅助,在微距或者拍摄纹理不明显的场景下好用). AF的大致原理就是检测图像锐度或者等价于锐度的参数,推动马达实现合焦或者对 ...

  3. 英语知识积累-D01-body+animal

    My body What's your name? Here are lots of children playing. Are they happy or sad? Who's waving at ...

  4. 印象笔记 MAC安装使用旧版本

    印象笔记终于支持markdown了,赞! 第一个beta版用起来非常不错.提示更新安装新版本后保存markdown一直提示 "Note content is invalid.",无 ...

  5. kaggle之泰坦尼克号乘客死亡预测

    目录 前言 相关性分析 数据 数据特点 相关性分析 数据预处理 预测模型 Logistic回归训练模型 模型优化 前言 一般接触kaggle的入门题,已知部分乘客的年龄性别船舱等信息,预测其存活情况, ...

  6. BZOJ5316 : [Jsoi2018]绝地反击

    若$R=0$,那么显然答案为离原点最远的点到原点的距离. 否则若所有点都在原点,那么显然答案为$R$. 否则考虑二分答案$mid$,检查$mid$是否可行. 那么每个点根据对应圆交,可以覆盖圆上的一部 ...

  7. emoji 表情: MySQL如何支持 emoji 表情

    https://www.cnblogs.com/jentary/p/6655471.html 修改数据库字符集: ALTER DATABASE database_name CHARACTER SET ...

  8. phantomjs api文档

    phantomjs实现了一个无界面的webkit浏览器.虽然没有界面,但dom渲染.js运行.网络访问.canvas/svg绘制等功能都很完备,在页面抓取.页面输出.自动化测试等方面有广泛的应用. 详 ...

  9. vue相关文件说明(基于vue2.0)

    1.config:生产,开发环境配置参数 2.static:第三方资源,这里面的文件直接写路径,不能用'import'导入 3.node_modules:引入一些依赖包 4..babelrc:定义了E ...

  10. 818C.soft thief

    Yet another round on DecoForces is coming! Grandpa Maks wanted to participate in it but someone has ...