您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

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

时间:2020-09-18 09:58:47  来源:  作者:

1.软件打包安装程序

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

2. 建立FTP服务器

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

3. 客户端程序开发

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

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

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

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

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

运行界面1


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

运行界面2


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

提示框

问题:

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

 

解决方案:

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

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

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

 

代码如下:

from update import Ui_MainWindow
from PyQt5 import QtWidgetsfrom PyQt5.QtWidgets import QMessageBoximport sysimport osfrom ftplib import FTP  # 引入ftp模块import win32processfrom PyQt5.QtCore import QBasicTimer, QThread, pyqtSignalimport timemycurrent_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_())
界面如下

 

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


Tags:Pyqt5   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1.软件打包安装程序利用setupfactory软件进行客户端软件打包,形成一个setup安装程序。2. 建立FTP服务器利用quickeasyftpserver在远程服务器中建立FTP服务器,放置2个文件,一个s...【详细内容】
2020-09-18  Tags: Pyqt5  点击:(303)  评论:(0)  加入收藏
一、简介在Qt(和大多数用户界面)中,“小部件”是用户可以与之交互的UI组件的名称。用户界面由布置在窗口内的多个小部件组成。Qt带有大量可用的小部件,也允许您创建自己的自定义...【详细内容】
2020-08-21  Tags: Pyqt5  点击:(66)  评论:(0)  加入收藏
引言对于Python下桌面软件的开发已经有了很多数据可视化的库,如Matplotlib、Seaborn、Pyqtgraph、Plotly等等,但这些库更适合于后端程序员的软件开发。实际上在前端网页开发方...【详细内容】
2020-05-06  Tags: Pyqt5  点击:(729)  评论:(0)  加入收藏
前言文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理。作者:朱淑强PS:如有需要Python学习资料的小伙伴...【详细内容】
2020-04-07  Tags: Pyqt5  点击:(34)  评论:(0)  加入收藏
PyQt5 是用来创建Python GUI应用程序的第三方工具包,它不仅与Python有着良好的兼容性,还可以通过可视化拖拽的方式进行窗体的创建,提高开发人员的工作效率,因此深受开发人员的喜...【详细内容】
2019-12-13  Tags: Pyqt5  点击:(345)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的  程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条