python 实现软件更新

python桌面软件版本在线更新

1.主程序
2.启动程序
3.更新程序

流程:程序入口为启动程序,双击启动程序。启动程序获取本地,和远程服务器版本,然后对比,再判断是否 进行更新

代码如下
import requests
import subprocess
import os
import keepachangelog
class launch_app():

def __init__(self) -> None:
    remote_info_url = "http://192.168.3.107/info.json"
    remote_version  = self.get_remote_version(remote_info_url)
    local_version   = self.get_version()

    ret = self.compared_version(local_version,remote_version)

    if  ret == -1:
        update_app = subprocess.Popen("update_app.exe")
        update_app.wait()

    else:
        path = os.path.join(os.getcwd(),'tof_measurement_tool.dist\\tof_measurement_tool.exe')
        tof_measurement_tool = subprocess.Popen(path)   
        tof_measurement_tool.wait()
        


def get_version(self):
    changelog = keepachangelog.to_dict(os.path.join(os.getcwd(), 'tof_measurement_tool\\CHANGELOG.md'))
    return list(changelog.keys())[0]

def get_remote_version(self,url):
    context_res = requests.get(url)
    version =  context_res.json()['version']
    return version


def compared_version(self,ver1, ver2):
    list1 = str(ver1).split(".")
    list2 = str(ver2).split(".")
    # 循环次数为短的列表的len
    for i in range(len(list1)) if len(list1) < len(list2) else range(len(list2)):
        if int(list1[i]) == int(list2[i]):
            pass
        elif int(list1[i]) < int(list2[i]):
            return -1
        else:
            return 1
    # 循环结束,哪个列表长哪个版本号高
    if len(list1) == len(list2):
        return 0
    elif len(list1) < len(list2):
        return -1
    else:
        return 1

if name == ‘main’:
launch_app()

更新成程序代码:

import os
import requests
import hashlib
import zipfile
import shutil
try:
from update_app.update_app_ui import Ui_Dialog
except ImportError :
from update_app_ui import Ui_Dialog
from PyQt6.QtCore import pyqtSignal,QThread,Qt
from PyQt6.QtWidgets import QDialog
from datetime import datetime
import time
import subprocess

class down_file_thread(QThread):
update_speed_sig = pyqtSignal(str)
update_percent_sig = pyqtSignal(int)

def __init__(self,parent=None):  
    super().__init__(parent)
    self.temp = 0 
    self.temp_size = 0

def run(self):
    start_time=time.time()
    with open(self.path,'wb') as file:
        for chunk in self.context_res.iter_content(chunk_size=1024):
            if chunk:
                file.write(chunk)
                self.temp_size += len(chunk)
                percent=(self.temp_size/self.context_length)*100 
                if  int(percent) == 100:
                    self.update_speed_sig.emit('0 MB/s') 
                    self.update_percent_sig.emit(int(percent))  
                else:
                   self.update_percent_sig.emit(int(percent))              
                if time.time()-start_time>2:       
                    speed=self.formatFloat((self.temp_size-self.temp)/1024/1024/2) 
                    self.temp = self.temp_size
                    start_time = time.time()
                    self.update_speed_sig.emit(str(speed)+'MB/s')                     
            file.flush()
        file.close() 
   
def formatFloat(self,num):
       return '{:.2f}'.format(num)  

class show_log_thread(QThread):
update_log_sig = pyqtSignal(str)
def init(self,parent=None):
super().init(parent)

def run(self):
    for log in  self.update_log:
        self.update_log_sig.emit(log)

class update_app(QDialog):
def init(self):
super(update_app, self).init()
self.ui = Ui_Dialog()
self.ui.setupUi(self)
#ui设置
self.ui.speed_label.setText(“0 MB/s”)
self.ui.plainTextEdit_change_log.setFocusPolicy(Qt.FocusPolicy.NoFocus)
#本地版本
# self.local_version = version
#zip 和json信息链接
remote_shafile_url = “http://192.168.3.107/info.json”
remote_logfile_url = “http://192.168.3.107/index.html”
#下载下来的zip 文件sha
self.file_sha = ‘’
#下载的文件路径log
self.file_path = ‘’
#服务器软件sha信息
self.remote_info_sha = self.get_remote_sha_info(remote_shafile_url)
#服务器软件日志信息
self.remote_version,self.update_log = self.get_remote_log_info(remote_logfile_url)
#zip信息链接
remote_zipfile_url = f"http://192.168.3.107/tof_measurement_tool_v{self.remote_version}.zip"

    # if self.local_version != self.remote_version:
    # 备份文件
    # self.backup_local_file()    
    #显示日志线程
    self.show_log_thread = show_log_thread()
    self.show_log_thread.update_log = self.update_log
    self.show_log_thread.start()
    self.show_log_thread.update_log_sig.connect(self.show_update_log)
    #下载软件包
    self.down_load_remote_source(remote_zipfile_url)


def update_percent(self,msg):
    self.ui.progressBar.setValue(msg)


def update_speed(self,msg):
    self.ui.speed_label.setText(msg)

def show_update_log(self,msg):
    #更新展示
    self.ui.plainTextEdit_change_log.appendPlainText(msg)

#获取远程info 信息 下的 sha值
def get_remote_sha_info(self,url):
    context_res = requests.get(url)
    remote_sha =  context_res.json()['sha']
    return remote_sha

def get_remote_log_info(self,url):
    content = requests.get(url)
    content.encoding = content.apparent_encoding
    content = content.text
    remote_version = content.split('-')[0].split(' ')[-2].replace('[','').replace(']','')  
    update_log = content.split('\r\n')       
    return remote_version,update_log

def down_load_remote_source(self,url):  
    self.down_file_thread = down_file_thread()
    self.down_file_thread.update_percent_sig.connect(self.update_percent)
    self.down_file_thread.update_speed_sig.connect(self.update_speed)
    self.down_file_thread.finished.connect(self.down_load_finished)

    context_res = requests.get(url, stream=True)   
    self.context_length   = int(context_res.headers['Content-Length'])  #数据长
    self.file_path = context_res.headers['Content-Disposition'].split("=")[-1].replace('"',"").replace(';',"")
    self.file_type =  self.file_path.split('.')[-1]
    self.down_file_thread.path =  self.file_path
    self.down_file_thread.context_length  = self.context_length
    self.down_file_thread.context_res = context_res
    self.down_file_thread.start()

    
def down_load_finished(self):        
    #获取压缩包的sha值
    if  self.file_type == "zip":
        sha=hashlib.sha1() 
        file_size=os.path.getsize(self.file_path)             
        with open(self.file_path ,mode='rb') as f:
            while file_size>1024:
                content=f.read(1024)
                sha.update(content)
                file_size-=1024
            else:
                content=f.read(file_size)
                sha.update(content)
                file_size=0
        self.file_sha = sha.hexdigest()
        
    #解压zip 包
    if self.file_sha == self.remote_info_sha:
        zip = zipfile.ZipFile(self.file_path,'r')   
        zip.extractall()
        zip.close()
      
        #启动应用程序
        path = os.path.join(os.getcwd(),'tof_measurement_tool.dist\\tof_measurement_tool.exe')
        tof_measurement_tool =  subprocess.Popen(path)

        #删除多余zip 文件
        os.unlink(self.file_path)
        
        #关闭主程序
        self.close()
        tof_measurement_tool.wait()
        
        
    

  
#备份旧版本文件
def backup_local_file(self):  
    #创建备份目录
    backup_path = f'backup_{self.local_version}_{datetime.now().strftime("%Y-%m-%d-%H-%M-%S")}'
    if os.path.isdir(backup_path): 
        pass
    else:
        os.mkdir(backup_path)   
    #移动文件 
    for path  in os.listdir('.') :  
        file = os.path.join( '.',path)
        if file.endswith('py'):
            continue
        elif 'backup' in file:
            continue
        elif file.endswith('ui'):
            continue
        else:
            shutil.copy(file,backup_path)

if name == ‘main’:
import sys
from PyQt6 import QtWidgets
app = QtWidgets.QApplication(sys.argv)
app.setStyle(‘QtCurve’)
gui = update_app()
gui.show()
sys.exit(app.exec())

主程序 为你自己的应用程序

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值