使用Python与Tkinter实现桌面软件自动更新与进度提醒
针对桌面应用程序版本迭代需求,本文介绍如何使用Python结合Tkinter、requests与多线程技术,实现远程版本号比对、用户二次确认、后台安全下载及进度条实时显示。附带服务端JSON配置示例与完整客户端代码,帮助开发者快速构建轻量级软件更新模块。
功能目标与预期效果
该模块旨在为Python桌面程序提供一套完整的在线更新方案。启动时自动请求服务端接口获取最新版本号,若检测到新版本则弹出用户确认框;获得授权后,在后台开启独立线程下载更新包,同时通过Tkinter原生控件实时渲染下载进度。完成后自动关闭进度窗口并提示用户。以下为各阶段的标准UI表现:



准备条件
确保运行环境已安装基础依赖库。Tkinter随Python标准库自带,无需额外安装。网络请求需使用第三方库,提示交互推荐使用跨平台自动化库:
- 核心依赖:
tkinter、requests、_thread(或threading)、pyautogui - 环境要求:Python 3.6+,支持HTTP/HTTPS协议访问目标服务器
- 前置操作:配置好服务端版本信息接口,返回标准JSON数据
真实操作顺序
第1步:设计服务端版本响应格式
明确接口返回结构,确保客户端能解析版本号与下载地址。服务端需保持以下JSON键名一致:
{
"soft_version": "1.0.0",
"soft_url": "http://example.com/update/client_v1.0.0.exe"
}
第2步:构建版本比对与确认逻辑
客户端启动时调用检查接口,提取本地版本与远程版本。采用移除小数点的整型比较法避免字符串排序歧义。若新版存在,调用弹窗组件征求用户同意:
# 省略部分内部方法,完整类定义见下方代码块
latest_version = json_result['soft_version']
if soft_dialog.check_version():
if pyautogui.confirm(text='有新版本,是否更新', title='通知', buttons=['OK', 'Cancel']) == 'OK':
soft_dialog.init_ui(root=app)
soft_dialog.soft_download_with_thread()
第3步:执行后台下载与进度渲染
为防止阻塞主界面,将下载任务移交至子线程。通过HEAD请求预先获取文件总大小,随后以stream=True分块写入磁盘。每接收一块数据即更新DoubleVar变量,驱动进度条重绘。注意:更新可执行程序前务必对原安装目录或关键配置文件进行备份。
# 完整参考代码请见下方整体示例
第4步:清理线程状态与最终提示
文件写入完毕后停止进度动画,销毁临时窗口,最后由外部线程发送全局通知弹窗告知用户操作结束。此时可引导用户重启主程序加载新文件。
参考完整代码
import os
import _thread
import shutil
import subprocess
import sys
import requests
from tkinter import Tk, Label, IntVar, DoubleVar, HORIZONTAL, messagebox
from tkinter.ttk import Progressbar
import pyautogui
class SoftUpdateDialog:
def __init__(self, soft_version):
self.soft_update_url = 'http://your_server/web/share/version/update_demo'
self.soft_version = soft_version
def init_ui(self, root):
self.root = root
self.root.title('软件更新')
self.root.geometry('300x100')
self.progress_var = IntVar()
self.label_var = DoubleVar()
self.label_var.set(0.0)
label = Label(self.root, text='正在更新软件,请等待···')
label.pack(pady=5)
self.progress_bar = Progressbar(self.root, length=200, mode='indeterminate')
self.progress_bar.pack(pady=5)
def tip_show(self, msg):
"""消息提示"""
messagebox.showwarning('提示', msg)
def soft_download_with_thread(self):
'''开线程下载'''
url = self.soft_update_url
try:
req = requests.get(url, stream=True, verify=False)
except Exception:
self.tip_show('请检查网络设置,无法检测到网络连接')
return
if req is None or str(req.status_code) != '200':
self.tip_show('软件更新失败,请检查网络设置')
return
json_result = req.json()
latest_version = json_result['soft_version']
latest_soft_url = json_result['soft_url']
if self.compare_version(latest_version):
self.progress_var.set(0)
self.progress_bar.start(60)
_thread.start_new_thread(self._soft_download, (latest_soft_url, latest_version))
def check_version(self):
url = self.soft_update_url
try:
req = requests.get(url, stream=True, verify=False)
except Exception:
self.tip_show('请检查网络设置,无法检测到网络连接')
return
if req is None or str(req.status_code) != '200':
self.tip_show('软件更新失败,请检查网络设置')
return
json_result = req.json()
latest_version = json_result['soft_version']
return self.compare_version(latest_version)
def _update_progressbar(self):
'''更新进度条'''
self.progress_bar['value'] = self.label_var.get()
def _end_update(self):
'''结束更新'''
self.progress_bar.stop()
self.root.destroy()
def get_remote_file_size(self, url, proxy=None):
"""通过content-length头获取远程文件大小"""
try:
req = requests.head(url, proxies={'http': proxy, 'https': proxy} if proxy else None, verify=False)
fileSize = int(req.headers.get('Content-Length', 0))
return fileSize
except Exception:
return 0
def _soft_download(self, latest_url, latest_version):
'''软件下载'''
self.label_var.set(0.0)
lastest_name = os.path.basename(latest_url)
lastest_size = self.get_remote_file_size(latest_url)
start_size = 0
with requests.get(latest_url, stream=True, verify=False) as r:
with open(lastest_name, "wb") as f:
for chunk in r.iter_content(chunk_size=1024):
if not chunk:
continue
start_size += len(chunk)
f.write(chunk)
f.flush()
self.label_var.set(100.0 * start_size / lastest_size)
print('>> ok')
self._end_update()
def compare_version(self, latest_version):
return int(self.soft_version.replace('.', '')) < int(latest_version.replace('.', ''))
if __name__ == '__main__':
app = Tk()
app.geometry('0x0')
soft_dialog = SoftUpdateDialog(soft_version='0.0.5')
if soft_dialog.check_version() and pyautogui.confirm(text='有新版本,是否更新', title='通知', buttons=['OK', 'Cancel'])=='OK':
soft_dialog.init_ui(root=app)
soft_dialog.soft_download_with_thread()
app.mainloop()
pyautogui.alert(text='下载完成!', title='通知', button='好的👌🏻')
排错与维护提示
代码中使用了verify=False跳过SSL证书校验,适用于内网或测试环境。生产环境建议替换为有效的CA证书或移除该参数以确保传输安全。若进度条卡顿或未显示,请检查子线程是否正确触发了_update_progressbar逻辑,且主线程未因长时间同步调用而冻结。下载路径默认为脚本同级目录,可根据业务需求修改open()中的保存位置。所有涉及文件覆盖的操作,强烈建议在运行更新脚本前建立完整的项目备份清单。
简要总结
通过组合Tkinter界面控件、requests流式下载与Python多线程机制,可低成本搭建可靠的桌面端OTA升级通道。合理控制校验频率与分块大小,既能保证低带宽下的稳定拉取,又能提供平滑的用户体验反馈。以上就是使用Python与Tkinter实现桌面软件自动更新与进度提醒的详细内容,更多关于Python桌面应用开发、Tkinter图形界面设计的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













