百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

基于Pyqt5的C/S模式客户端在线升级方案

bigegpt 2024-09-17 12:44 5 浏览

1.软件打包安装程序

利用setupfactory软件进行客户端软件打包,形成一个setup安装程序。

2. 建立FTP服务器

利用quickeasyftpserver在远程服务器中建立FTP服务器,放置2个文件,一个setup安装文件,一个是ver.txt文件,里面写上软件的版本号12位,例如20200917V001。

3. 客户端程序开发

在客户端程序中点击升级按钮后

(1) 程序首先删除本地的上一次的版本和升级文件,然后从ftp服务器上下载ver.txt,然后判断服务器的setup版本和当前软版本是否一致,不一致,就提示用户升级。

(2) 如果用户同意升级,就在ftp上下载setup安装文件。

(3) 下载完成后,再开一个线程执行setup程序,然后把当前的程序关闭,安装程序会覆盖当前的程序。

问题:

这种方法比较简单,主要问题是不知道ftp文件的下载进度,会有一直卡死的现象。这个原因是进度条的定时器程序刷新UI和FTP下载程序在一个线程中,造成拥塞了。下载时就不能定时中断,刷新UI了


解决方案:

(1) 对于ftp下载采用异步方式,下载完后发送信号给主线程。

(2) 主线程点击升级按钮,绑定子线程和对应的回调函数。然后启动ftp子线程。

(3) 在回调函数中,执行此程序就是下载结束了,这时可以在主线程中启动,进度条满格,然后执行分线程执行安装程序,并在主程序中把自己结束


代码如下:

from update import Ui_MainWindow
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import QMessageBox
import sys
import os
from ftplib import FTP  # 引入ftp模块
import win32process
from PyQt5.QtCore import QBasicTimer, QThread, pyqtSignal

import time

mycurrent_ver = '20200916V001'  # 当前软件版本号
mynew_ver = ''

#异步线程
class MyCal(QThread):
   #自定义一个信号名
    cal_signal = pyqtSignal(int)  #定义信号返回的数值类型
    #构造函数
    def __init__(self, mypath, filename,parent=None):     #
        super(MyCal, self).__init__(parent)
        self.mypath = mypath
        self.filename=filename
        print("分线程:",self.mypath,self.filename)
    #析构函数
    def __del__(self):
        self.wait()
    #该线程主程序
    def run(self):
        ##ftp下载程序版本程序
        ftp = MyFtp('127.0.0.1)
        ftp.login('admin', '123456')
        ftp.downloadFile(self.mypath, '/down/',  self.filename)
        ftp.close()
        print("分线程下载结束:", self.mypath+self.filename)
        self.cal_signal.emit(1)          #发射信号,传参数




class MyFtp:
    ftp = FTP()

    def __init__(self, host, port=21):
        self.ftp.connect(host, port)

    def login(self, username, pwd):
        self.ftp.set_debuglevel(2)  # 打开调试级别2,显示详细信息
        self.ftp.login(username, pwd)
        print(self.ftp.welcome)

    def downloadFile(self, localpath, remotepath, filename):
        os.chdir(localpath)  # 切换工作路径到下载目录
        self.ftp.cwd(remotepath)  # 要登录的ftp目录
        self.ftp.nlst()  # 获取目录下的文件
        file_handle = open(filename, "wb").write  # 以写模式在本地打开文件
        self.ftp.retrbinary('RETR %s' % os.path.basename(filename), file_handle, blocksize=1024)  # 下载ftp文件
        # ftp.delete(filename)  # 删除ftp服务器上的文件

    def close(self):
        self.ftp.set_debuglevel(0)  # 关闭调试
        self.ftp.quit()


# 主窗体
class MainForm(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainForm, self).__init__()
        self.setupUi(self)
        self.timer = QBasicTimer()
        self.step = 0

        # self.myupdate_bt()

    # 进度条控制定时器
    def timerEvent(self, event):
        if self.step >= 100:
            self.timer.stop()
            self.pushButton_2.setText('开始进度条')
            self.step = 0
            self.progressBar.setValue(self.step)
            return
        self.step = self.step + 1
        if self.step>=99:
            self.step=99
        self.progressBar.setValue(self.step)

    # 进度条控制
    def myprocessbar_bt(self):
        pass
        if self.timer.isActive():
            self.timer.stop()
            self.pushButton_2.setText('开始进度条')

        else:
            self.timer.start(100, self)
            self.pushButton_2.setText('停止进度条')

    def myupdate_bt(self):
        pass
        myhomedir = os.getcwd()
        mypath = os.getcwd() + '\\down\\'
        myfilepath1 = mypath + "ver.txt"
        myfilepath2 = mypath + "setup.exe"
        # 删除文件
        x1 = os.path.exists(myfilepath1)  # True/False
        if x1 == True:
            print("删除文件:" + myfilepath1)
            os.remove(myfilepath1)
        x1 = os.path.exists(myfilepath2)  # True/False
        if x1 == True:
            print("删除文件:" + myfilepath2)
            os.remove(myfilepath2)

        ##ftp下载程序版本程序
        ftp = MyFtp('127.0.0.1)
        ftp.login('admin', '123456')
        ftp.downloadFile(mypath, '/down/', 'ver.txt')
        ftp.close()
        print("下载结束:", myfilepath1)
        # 判断版本
        with open(myfilepath1, 'rt') as f1:
            mynew_ver = f1.readline()[0:12]
            self.label_4.setText(mynew_ver)
            self.label_2.setText(mycurrent_ver)
        if mynew_ver != mycurrent_ver:
            x1 = QMessageBox.information(self, "确认信息", "有新版本,确认是否升级", QMessageBox.Yes | QMessageBox.No)
            if x1 == QMessageBox.No:
                os.chdir(myhomedir)
                return
            print("开始升级")
            QMessageBox.information(self, "确认信息", "开始下载程序!!")
            self.myprocessbar_bt()#显示进度条
            # self.timer.start(100, self)

            ##拥塞ftp下载程序
            # ftp = MyFtp('127.0.0.1')
            # ftp.login('admin', '123456')
            # ftp.downloadFile(mypath, '/down/', 'setup.exe')
            # ftp.close()
            # print("下载结束:", myfilepath2)
            # QMessageBox.information(self, "确认信息", "下载程序结束!!")
            ####异步FTP下载
            self.cal = MyCal(mypath, 'setup.exe')  # 点击按钮后新建计算的线程
            self.cal.cal_signal.connect(self.cal_callback)  # 连接计算线程的信号
            self.cal.start()  # 开始运行线程
        else:
            QMessageBox.information(self, "确认信息", "已经是最新版本,不用升级")
            os.chdir(myhomedir)
            return

        # 省略 使用接收到线程返回的参数
        ###执行第三方程序,新线程
        #win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())
        os.chdir(myhomedir)
        print("主程序退出")
        #sys.exit()

    def cal_callback(self):  # 接收到计算线程信号后的回掉函数
        pass
        print('异步ftp下载结束')
        self.step=100
        self.progressBar.setValue(self.step)
        #self.myprocessbar_bt()#显示进度条
        myhomedir = os.getcwd()
        mypath = myhomedir
        myfilepath1 = mypath + "\\ver.txt"
        myfilepath2 = mypath + "\\setup.exe"
        QMessageBox.information(self, "确认信息", "下载结束,开始升级")
        print(myfilepath2)
        win32process.CreateProcess(myfilepath2, '', None, None, 0, win32process.CREATE_NO_WINDOW, None, None,win32process.STARTUPINFO())
        sys.exit()




# 主程序入口
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    win_main = MainForm()
    win_main.show()
    sys.exit(app.exec_())
界面如下


相关推荐

方差分析简介(方差分析通俗理解)

介绍方差分析(ANOVA,AnalysisofVariance)是一种广泛使用的统计方法,用于比较两个或多个组之间的均值。单因素方差分析是方差分析的一种变体,旨在检测三个或更多分类组的均值是否存在...

正如404页面所预示,猴子正成为断网元凶--吧嗒吧嗒真好吃

吧嗒吧嗒,绘图:MakiNaro你可以通过加热、冰冻、水淹、模塑、甚至压溃压力来使网络光缆硬化。但用猴子显然是不行的。光缆那新挤压成型的塑料外皮太尼玛诱人了,无法阻挡一场试吃盛宴的举行。印度政府正...

Python数据可视化:箱线图多种库画法

概念箱线图通过数据的四分位数来展示数据的分布情况。例如:数据的中心位置,数据间的离散程度,是否有异常值等。把数据从小到大进行排列并等分成四份,第一分位数(Q1),第二分位数(Q2)和第三分位数(Q3)...

多组独立(完全随机设计)样本秩和检验的SPSS操作教程及结果解读

作者/风仕在上一期,我们已经讲完了两组独立样本秩和检验的SPSS操作教程及结果解读,这期开始讲多组独立样本秩和检验,我们主要从多组独立样本秩和检验介绍、两组独立样本秩和检验使用条件及案例的SPSS操作...

方差分析 in R语言 and Excel(方差分析r语言例题)

今天来写一篇实际中比较实用的分析方法,方差分析。通过方差分析,我们可以确定组别之间的差异是否超出了由于随机因素引起的差异范围。方差分析分为单因素方差分析和多因素方差分析,这一篇先介绍一下单因素方差分析...

可视化:前端数据可视化插件大盘点 图表/图谱/地图/关系图

前端数据可视化插件大盘点图表/图谱/地图/关系图全有在大数据时代,很多时候我们需要在网页中显示数据统计报表,从而能很直观地了解数据的走向,开发人员很多时候需要使用图表来表现一些数据。随着Web技术的...

matplotlib 必知的 15 个图(matplotlib各种图)

施工专题,我已完成20篇,施工系列几乎覆盖Python完整技术栈,目标只总结实践中最实用的东西,直击问题本质,快速帮助读者们入门和进阶:1我的施工计划2数字专题3字符串专题4列表专题5流程控制专题6编...

R ggplot2常用图表绘制指南(ggplot2绘制折线图)

ggplot2是R语言中强大的数据可视化包,基于“图形语法”(GrammarofGraphics),通过分层方式构建图表。以下是常用图表命令的详细指南,涵盖基本语法、常见图表类型及示例,适合...

Python数据可视化:从Pandas基础到Seaborn高级应用

数据可视化是数据分析中不可或缺的一环,它能帮助我们直观理解数据模式和趋势。本文将全面介绍Python中最常用的三种可视化方法。Pandas内置绘图功能Pandas基于Matplotlib提供了简洁的绘...

Python 数据可视化常用命令备忘录

本文提供了一个全面的Python数据可视化备忘单,适用于探索性数据分析(EDA)。该备忘单涵盖了单变量分析、双变量分析、多变量分析、时间序列分析、文本数据分析、可视化定制以及保存与显示等内容。所...

统计图的种类(统计图的种类及特点图片)

统计图是利用几何图形或具体事物的形象和地图等形式来表现社会经济现象数量特征和数量关系的图形。以下是几种常见的统计图类型及其适用场景:1.条形图(BarChart)条形图是用矩形条的高度或长度来表示...

实测,大模型谁更懂数据可视化?(数据可视化和可视化分析的主要模型)

大家好,我是Ai学习的老章看论文时,经常看到漂亮的图表,很多不知道是用什么工具绘制的,或者很想复刻类似图表。实测,大模型LaTeX公式识别,出乎预料前文,我用Kimi、Qwen-3-235B...

通过AI提示词让Deepseek快速生成各种类型的图表制作

在数据分析和可视化领域,图表是传达信息的重要工具。然而,传统图表制作往往需要专业的软件和一定的技术知识。本文将介绍如何通过AI提示词,利用Deepseek快速生成各种类型的图表,包括柱状图、折线图、饼...

数据可视化:解析箱线图(box plot)

箱线图/盒须图(boxplot)是数据分布的图形表示,由五个摘要组成:最小值、第一四分位数(25th百分位数)、中位数、第三四分位数(75th百分位数)和最大值。箱子代表四分位距(IQR)。IQR是...

[seaborn] seaborn学习笔记1-箱形图Boxplot

1箱形图Boxplot(代码下载)Boxplot可能是最常见的图形类型之一。它能够很好表示数据中的分布规律。箱型图方框的末尾显示了上下四分位数。极线显示最高和最低值,不包括异常值。seaborn中...