如何使用PyUpdater实现PyInstaller打包Tkinter程序的自动更新
PyUpdater实现Tkinter(PyInstaller打包)exe自动更新落地步骤
PyUpdater是对PyInstaller适配最成熟的自动更新框架,按下面步骤操作即可快速实现需求:
前置环境配置
- 安装所需依赖,执行命令:
pip install pyupdater pyinstaller
项目初始化
在你的main.py所在的项目根目录执行初始化命令:pyupdater init
交互选项按实际情况填写即可:
- 打包后端选择
PyInstaller,和你现有打包逻辑完全对齐 - 填写自定义的应用名、开发者名,后续代码配置会用到这两个值
- 初始化完成后根目录会生成
pyu.cfg配置文件和pyu-data工作目录,不要手动修改或删除
入口代码修改
把更新检测逻辑放在Tkinter主窗口实例化之前,避免运行中exe被进程占用导致替换失败,直接复用下面的代码片段到你的main.py中:
from pyupdater.client import Client import sys import tkinter as tk from tkinter import messagebox # 替换为你初始化时填写的配置信息 class AppUpdateConfig: APP_NAME = "你的Tkinter应用名" COMPANY_NAME = "你填写的开发者名" # 部署目录地址:支持http静态服务路径、本地/内网共享文件夹的file协议路径 UPDATE_URLS = ["你的更新部署目录地址,末尾必须带斜杠/"] PUBLIC_KEY = None # 第一次打包生成密钥后回填到这里 def run_update_check(current_version: str): client = Client(AppUpdateConfig) # 检测稳定通道更新 update_obj = client.update_check( AppUpdateConfig.APP_NAME, current_version, channel="stable" ) if not update_obj: return # 无新版本直接启动主程序 # 调用原生Tkinter提示框,无需引入额外依赖 _tmp_root = tk.Tk() _tmp_root.withdraw() user_confirm = messagebox.askyesno( "版本更新", f"检测到新版本v{update_obj.version},是否立即下载更新?" ) _tmp_root.destroy() if user_confirm: update_obj.download() if update_obj.is_downloaded(): # 自动解压替换旧exe并重启程序 update_obj.extract_restart() sys.exit(0) if __name__ == "__main__": # 先执行更新检测,再启动主程序 CURRENT_VERSION = "1.0.0" # 每次发新版本修改这里的版本号 run_update_check(CURRENT_VERSION) # === 下方接你原有的Tkinter主程序逻辑 === # root = tk.Tk() # 你的原有界面、业务代码 # root.mainloop()
打包&首次发布流程
- 首次打包执行命令,你原来传给PyInstaller的参数(比如
-w隐藏控制台、-i设置图标、-F单文件打包)直接拼接在命令末尾即可:pyupdater build --app-version=1.0.0 -w -i 你的图标文件.ico main.py - 生成签名密钥,执行
pyupdater keys --create,命令执行完会输出一串PUBLIC_KEY,把这个值复制回填到上面代码里AppUpdateConfig的PUBLIC_KEY字段,重新执行一次上述build命令,否则更新包签名校验会失败 - 生成部署更新包,依次执行两条命令:
pyupdater pkg --processpyupdater pkg --sign - 部署:把
pyu-data/deploy目录下的所有文件全部复制/上传到你之前填写的UPDATE_URLS对应的目录即可,首次发给用户的安装包存放在pyu-data/new目录里
后续版本更新操作
每次发布新版本只需要三步:
- 把代码里的
CURRENT_VERSION改成对应的新版本号(比如1.0.1) - 重新执行
pyupdater build --app-version=对应新版本号 你的原有打包参数 main.py - 依次执行
pyupdater pkg --process、pyupdater pkg --sign,把新生成的deploy目录内容覆盖到部署目录即可,老用户启动程序时会自动检测到更新
常见踩坑
- 绝对不要在Tkinter主窗口启动后再调用
extract_restart(),否则exe被进程占用会导致替换失败 - 用本地/内网共享文件夹部署时,
UPDATE_URLS要写成file:///共享文件夹的绝对路径/格式,末尾斜杠不能丢 - 初始化生成的密钥文件存放在
pyu-data/keys.py,一定要备份,丢失后新打的更新包签名不匹配,老版本将无法收到更新 - 如果你之前已经写了自定义的PyInstaller spec文件,打包时直接加
--specfile=你的spec文件路径参数,不用重新配置打包规则
内容的提问来源于stack exchange,提问作者Malou
相关产品推荐
相关产品推荐

