用Python实现一个软件自动升级系统

目录

一、服务端

1. XML配置文件

 2. 服务端代码设计

二、客户端

1. XML配置文件

2. 客户端代码设计

三、运行效果

1. 程序目录结构

2. 服务端运行效果

3. 客户端运行效果

四、改进思路

五、文件下载

软件客户端在发布新版本的时候,有时候只修改了几个文件,没必要让用户重新下载整个客户端再重新安装,同时也不应要求用户每次去手动下载更新的文件,再手动覆盖本地文件。这个时候需要设计一个自动升级机制,在某些条件触发时(比如软件启动的时候)自动查看是否有更新,如果有就将改变的内容下载下来,更新本地旧文件,再根据情况判断是否重启客户端。这个功能现在是桌面程序必备的功能,基本所有的客户端都有这个检查更新的功能。我曾经用Python实现过一个基于http下载的简易自动升级系统,可以独立运行、复用在不同的情景下。

设计思路很简单:当有新版本需要发布时,将文件放在服务端,生成一个记录每个文件变化的配置文件。客户端本地也有一个记录文件信息的配置文件,客户端检查更新时,将服务端的配置文件下载下来,与本地配置文件进行比较,然后下载有变化的文件,覆盖本地文件(如果文件正在使用中,可能无法覆盖,这时候更新前应该先关闭正在运行的客户端),中间有Tkinter做的界面提示更新进度。更新结束后根据策略决定是否重启客户端。

一、服务端

服务端要做的事,首先是选择一个端口号,开启用于响应客户端下载的http服务。然后把指定的目录下的所有文件都扫描一遍,给每个文件记录一个版本号和最后修改日期,再生成一个总版本号,写在XML配置文件里。

比如版本号从0开始,第一次发布程序时,每个文件的版本号都是0,总版本号也是0,第二次发布时,扫描每个文件的最后修改日期,如果日期大于XML文件中记录的日期,将这个文件的记录日期更新,版本号加1。扫描完毕,只要有任意文件的版本号发生变化,总版本号也加1。这样客户端在检查更新时,只需要先比较服务端的总版本号和自己本地的总版本号是否一致。如果不一致,再下载XML文件比较每一个文件版本号变化,如果一致就不用下载XML文件比较了(可以在服务端增加一个接口,客户端请求这个接口时返回一个总版本号字段)。

1. XML配置文件

1.1 XML配置文件结构

ServerInfo节点:记录服务端IP和端口号,可以让客户端知道去哪里下载,当下载地址或端口号变化时,通过更新这个节点,客户端下次更新时就会到新的地址和端口号下载。

ClientVersion节点:要升级的模块的文件信息,包含1个总版本号属性,子节点包括该模块下每个文件的相对路径、文件大小、最后更新时间和版本号。这个节点可以设计多个,用不同的节点名,区分不同的模块,每个模块都有自己的总版本号。这里以1个模块为例。

1.2 XML配置文件示例:

<?xml version="1.0" encoding="utf-8"?>
<versionInfo>
    <ServerInfo>
        <ServerIp>202.169.100.52</ServerIp><!--服务端ip地址-->
        <ServerPort>8888</ServerPort><!--服务端端口号-->
        <XmlLocalPath>client_path</XmlLocalPath><!--存放文件的路径-->
    </ServerInfo><!--服务端信息-->
    <ClientVersion Version="11">
        <object>
            <FileRelativePath>ClientVersion/cfg.ini</FileRelativePath><!--文件相对路径-->
            <FileSize>177</FileSize><!--文件大小B-->
            <LastUpdateTime>2019-04-29 16:27:35</LastUpdateTime><!--文件最后修改时间-->
            <Version>10</Version><!--文件版本号-->
        </object><!--文件节点-->
        <object>
            <FileRelativePath>ClientVersion/Scripts/config.py</FileRelativePath><!--文件相对路径-->
            <FileSize>6567</FileSize><!--文件大小B-->
            <LastUpdateTime>2019-04-02 14:37:57</LastUpdateTime><!--文件最后修改时间-->
            <Version>1</Version><!--文件版本号-->
        </object><!--文件节点-->
    </ClientVersion><!--总版本号-->
</versionInfo>

 1.3 XML处理代码:

新建一个处理XML文件的类,服务端和客户端通用,主要是一些XML的增删改查功能。

# 处理xml的类
class VersionInfoXml():
    def __init__(self, xml_path, server_info=None, module_list=None):
        self.xml_path = xml_path
        if server_info is not None:
            if module_list is None:
                module_list = ["ClientVersion"]
            self.create_new_xml(server_info, module_list)
        self.tree = ET.parse(self.xml_path)
        self.root = self.tree.getroot()

    def create_new_xml(self, server_info, module_info):
        root = ET.Element("versionInfo")
        ServerInfo = ET.SubElement(root, "ServerInfo")
        ET.SubElement(ServerInfo, "ServerIp").text = server_info[0]
        ET.SubElement(ServerInfo, "ServerPort").text = server_info[1]
        ET.SubElement(ServerInfo, "XmlLocalPath").text = server_info[2]
        for each_module in module_info:
            ET.SubElement(root, each_module).set("Version", "0")
        self.save_change(root)
        print("I created a new temp xml!")

    def save_change(self, root=None):
        if root is None:
            root = self.root
        rough_bytes = ET.tostring(root, "utf-8")
        rough_string = str(rough_bytes, encoding="utf-8").replace("\n", "").replace("\t", "").replace("    ", "")
        content = minidom.parseString(rough_string)
        with open(self.xml_path, 'w+') as fs:
            content.writexml(fs, indent="", addindent=
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值