简介:本资源为PySimpleGUI 4.60.5官方老版本源码安装包,面向Python GUI初学者、教学开发者及需规避商业授权限制的轻量级桌面应用制作者。当前pip默认仅支持收费版≥5.0(含30天试用提示),而该版本完全免费且无运行时限制,适用于数据录入工具、本地监控面板、教学演示界面等无需高级特性的实用场景。压缩包共13个文件,含5个核心Python源码文件(含setup.py)、4个说明与配置文本(含安装指引)、2个元信息文件(PKG-INFO与egg-info)及cfg/egg等构建相关文件,结构完整,可直接本地pip install .部署,总大小仅1.91MB,轻量易用。已有365人学习下载,提供开箱即用的老版本源码、清晰的包内模块组织(含dist/build/egg-info标准布局)及免依赖的纯Python安装路径,助用户绕过许可壁垒,快速启动GUI开发实践。
1. 为什么我在一堆GUI库里翻出PySimpleGUI 4.60.5来用
如果你写Python写了几年,大概率会有这种感觉:命令行工具跑得飞起,但一到要给同事、客户或者自己做个带窗口的小工具,就头大。Tkinter太丑,PyQt太重,wxPython文档读起来像天书。但活儿总得干,于是每次做GUI都得重新翻一遍资料,时间全耗在“怎么画一个能看的窗口”上了。
我也是这么过来的,直到有一回,我需要在两天内给运营团队做一个小工具——功能很简单:读取Excel里的订单列表,允许用户勾选需要导出的行,然后在每个订单文件夹里生成一个说明txt。看起来不难,但用Tkinter写的话,表格控件和数据绑定的代码量能让我写到怀疑人生。后来我查到一个库叫PySimpleGUI,看了几个示例,半小时就把原型跑通了。那个版本,正好是4.60.5。
现在网上搜“PySimpleGUI 4.60.5 老版本 免费.zip”,其实大部分来源是各种下载站打包好的资源,甚至有的里面带的是Windows下的exe安装包。这背后有个很实际的需求:不是所有人都在用最新版,很多生产线上的Python环境还是3.7、3.8,而某些老版本库对新版PySimpleGUI的接口有依赖。记得当时我后端有个服务用的第三方库,内部调用的是sg.FlexForm这个老接口,后来新版里改名成了sg.Window,一升级就崩。所以4.60.5这个老版本,在特定环境下反而比最新版香。
这篇文章,我把自己实际用4.60.5做工具时走过的路、踩过的坑、封装过的代码都整理一遍。不管你是刚刚接触PySimpleGUI,还是遇到了“新版本和旧项目冲突”这种尴尬问题,后面这些内容应该都能帮上忙。
2. 4.60.5这个版本处于什么位置:为什么“老版本”反而有人到处找
2.1 PySimpleGUI的版本演进简述
PySimpleGUI的版本号走得其实不快,但接口变化挺大。从4.x到4.60.5,核心API已经非常稳定,sg.Window、sg.Text、sg.Input、sg.Button、sg.Listbox这些基础组件的用法在整个4.x生命周期内几乎没变过。4.60.5发布时间大概是2022年,那是PySimpleGUI最热闹的时期,官方文档齐全,社区示例多,Stack Overflow上一搜一大把答案。
进入5.x之后,PySimpleGUI做了不少重大调整,包括对ttk主题的更深层支持、某些参数被废弃,以及底层事件循环实现的改动。我印象最深的是5.x把Button的key参数行为做了清理,以前可以传字符串,新版要求更严格的格式。如果你维护的项目里有一堆老代码,升级之后最直观的感受就是:运行时突然弹出一堆DeprecationWarning,甚至直接TypeError。
2.2 “免费”这两个字的真实含义
网络上热词“pysimplegui免费”其实指向一个很多人关心的问题:这个库到底收不收费?
PySimpleGUI的授权模式分界点就在4.60.5附近。严格来说,更早的4.x版本是LGPL授权,对个人和商业项目都很友好,你可以随便用,也可以集成到商业软件里,只要遵循LGPL对修改后代码的开源要求就行。而PySimpleGUI从某个版本开始转向了“商业使用需要购买授权”的模式,个人学习和非商业项目仍然免费。这就导致了一个很现实的情况:很多企业内部的自动化脚本、数据处理工具,如果早就基于4.60.5开发完并且跑得好好的,谁都不会为了“升级”去自找麻烦。反正4.60.5能覆盖的需求,新的5.x也不一定用得上,反而可能因为授权变化惹出合规风险。
所以你在下载站看到一个“老版本免费.zip”的压缩包,本质上它是社群用户保存的PyPI镜像或者wheel包,方便局域网内安装、离线环境部署。这不是什么破解版,就是官方那个开源阶段发布的纯净安装包,只是下载站给它贴了一个“免费”标签,容易让人误会。
2.3 我为什么没升到最新版
当时我把这个订单导出工具做完后,同事问我为什么不用最新版。我说三个原因:
- 项目跑在服务器上,Python版本是3.7,新版PySimpleGUI对Python版本的最低要求更高,装不上。
- 代码里用了
sg.SetOptions这个旧方法,新版直接移除了。 - 我写的工具打包成了exe给运营同事用,PyInstaller对新版的支持不够好,打包出来的程序在Windows 7上打不开。
这三个问题一出来,升级的念头就断了。如果你也遇到类似情况,建议直接把环境锁在4.60.5,踏踏实实用,没必要跟风。
3. 从零安装4.60.5:wheel包、pip源和离线部署三种方式
3.1 确定你的Python版本兼容性
安装前第一件事是确认Python环境。PySimpleGUI 4.60.5支持Python 3.6到3.9,对Python 3.10以上支持不太好,3.11基本装不上。所以服务器上是Python 3.7或者3.8,那正好;如果是3.10+,建议用虚拟环境跑老版本,别把系统环境搞乱了。
可以用这个命令查当前Python版本:
python --version3.2 在线pip安装
最简单的方式,直接从PyPI指定版本安装:
pip install PySimpleGUI==4.60.5如果网络状况一般,或者在公司内网,可以加镜像源:
pip install PySimpleGUI==4.60.5 -i https://pypi.tuna.tsinghua.edu.cn/simple安装完验证一下:
python -c "import PySimpleGUI as sg; print(sg.__version__)"输出4.60.5就说明环境OK了。
3.3 离线安装wheel包
下载站那个“PySimpleGUI-4.60.5老版本免费.zip”,解压后里面通常是一个.whl文件或者.tar.gz源码包。不管哪种,在联网机器上下载好,拷到目标机器上,然后:
pip install PySimpleGUI-4.60.5-py3-none-any.whl如果下载站给你的是源码包:
pip install PySimpleGUI-4.60.5.tar.gz注意whl文件名中的py3-none-any表示纯Python包,不依赖特定平台,Windows、Linux、macOS都能装。
3.4 离线部署到多台机器的小技巧
如果你要给公司几十台电脑装,一台台pip install太累了。我当时的做法是:
mkdir pysimplegui_package cd pysimplegui_package pip download PySimpleGUI==4.60.5 -d ./这样会把包和它的依赖都下载到当前目录,然后打包成一个文件夹,在别的机器上执行:
pip install --no-index --find-links=./pysimplegui_package PySimpleGUI这样即使目标机器完全没外网,也能顺利安装。
注意:4.60.5本身不依赖其他第三方库,但如果你之前没装过
Pillow或者opencv-python,某些图像处理功能会不可用。离线安装时建议把Pillow也一起下载。
4. 用4.60.5写一个文件批量整理工具:核心代码与设计思路
4.1 工具要解决什么问题
我以一个实际做过的工具为例:批量整理下载目录里的文件。具体需求是:
- 打开一个窗口,显示指定目录下所有文件。
- 用户可以选择要处理的文件,勾选或者点选。
- 点击“开始整理”,程序根据文件扩展名自动移动到不同子文件夹(图片、文档、压缩包、其他)。
- 窗口上实时显示处理进度和结果。
这个工具用PySimpleGUI来做非常顺,因为它的Listbox和Button足够干活了。
4.2 核心代码实现
先导入库,定义文件分类规则:
import PySimpleGUI as sg import os import shutil # 定义文件分类规则 RULES = { "图片": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp"], "文档": [".pdf", ".docx", ".doc", ".txt", ".xlsx", ".xls", ".pptx"], "压缩包": [".zip", ".rar", ".7z", ".tar", ".gz"], "其他": [] }构建窗口布局。PySimpleGUI 4.60.5的布局就是一个嵌套列表,每个元素代表一行:
layout = [ [sg.Text("目标文件夹"), sg.Input(key="-FOLDER-"), sg.FolderBrowse("浏览")], [sg.Text("文件列表"), sg.Listbox(values=[], size=(80, 15), key="-FILELIST-", select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED)], [sg.Checkbox("按扩展名自动分类", default=True, key="-AUTO-")], [sg.Button("开始整理"), sg.Button("刷新列表"), sg.Button("退出")], [sg.Output(size=(100, 8), key="-OUTPUT-")] ] window = sg.Window("批量文件整理工具", layout, font=("微软雅黑", 11))注意这里用sg.Output来显示处理日志,它会把print输出捕获到窗口里,调试和用户反馈都方便。
主循环是PySimpleGUI的核心模式:
def list_files(folder): try: return os.listdir(folder) except Exception as e: return [f"ERROR: {e}"] while True: event, values = window.read() if event in (sg.WIN_CLOSED, "退出"): break if event == "刷新列表": folder = values["-FOLDER-"] if folder: window["-FILELIST-"].update(values=list_files(folder)) if event == "开始整理": folder = values["-FOLDER-"] selected_files = values["-FILELIST-"] if not folder or not selected_files: print("请先选择文件夹和文件") continue print(f"开始处理 {len(selected_files)} 个文件...") for filename in selected_files: src = os.path.join(folder, filename) if not os.path.isfile(src): continue ext = os.path.splitext(filename)[1].lower() dest_folder = "其他" for category, exts in RULES.items(): if ext in exts: dest_folder = category break dest_path = os.path.join(folder, dest_folder) os.makedirs(dest_path, exist_ok=True) shutil.move(src, os.path.join(dest_path, filename)) print(f"移动: {filename} -> {dest_folder}/") print("整理完成!")4.3 为什么这样设计
这里有几个关键设计点。select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED是让用户可以用Ctrl/Shift多选文件,比一个个勾选快很多。FolderBrowse是PySimpleGUI封装的系统文件夹选择组件,比手动输入路径体验好得多。加一个“刷新列表”按钮是因为我遇到过文件夹路径变化但列表不同步的问题,后来干脆做个手动刷新,省心。
之前有读者问我为什么不直接用sg.Table按列显示文件大小、修改日期。其实sg.Table在这版本也能用,但Listbox在多选和上下键操作上更顺手,而且代码更短。做内部工具,简单优先。
4.4 运行过程中的意外情况
我写完后自己测试,第一个版本在点击“开始整理”时直接把窗口卡死了。原因是文件数量特别多时(几千个文件),移动操作是同步阻塞的,窗口无法响应。后来改成用window["-OUTPUT-"].update("")配合window.refresh()在每次移动后刷新界面,或者把文件处理放到线程里:
import threading def process_files_thread(folder, selected_files): for filename in selected_files: # 处理逻辑 print(...) window.write_event_value("-REFRESH-", None) # 通过事件通知主循环刷新 if event == "开始整理": threading.Thread(target=process_files_thread, args=(folder, selected_files), daemon=True).start()write_event_value是4.60.5里好用的线程安全通信方法,可以在子线程里向主循环发送事件,这样窗口不会卡死。这一点一定要记住,PySimpleGUI的单线程模型是很多人初用时最容易碰到的坑。
5. 老版本实测:性能表现与界面优化的几个细节
5.1 界面响应速度和资源占用
用4.60.5做的窗口工具,启动速度和界面流畅度都算中上水平。做过一个简单的测试:同样一个包含500个文件、每次刷新都要重新读取目录内容的窗口,4.60.5从启动到渲染完成大约0.8秒,而Tkinter直写大约0.4秒,PyQt大约1.2秒。虽然4.60.5比原生Tkinter慢一点,但开发效率的提升完全值得这个差距。
内存方面,一个普通工具窗口约占35MB~50MB内存,这主要看系统字体渲染和控件数量。如果你是做数据处理的,跑完窗口再关掉,内存会正常释放,不太需要担心泄漏问题。
这段经验分享给那些拿PySimpleGUI做商业软件界面的人:4.60.5完全能扛住日常工具的需求,但如果你的窗口里塞了几百个控件且频繁更新,建议用window.finalize()把窗口先实例化,再通过window[key].update()快速更新。
5.2 字体与中文显示的处理
4.60.5默认字体在Windows上是Arial,显示中文全是方块。第一件事就是全局设置中文字体:
sg.SetOptions(font=("微软雅黑", 10))在macOS上,用("PingFang SC", 12)效果更好。Linux上则是("Noto Sans CJK SC", 11)。建议把字体设置写在所有窗口创建之前,这样所有控件都会继承默认字体,不用一个控件一个控件去设。
另一个小坑:sg.Text的size参数,第二个值是字符宽度,中文按双字符宽度计算。比如想要显示10个中文字符的位置,size要设成(20, 1),否则文字会截断,排列也会错位。
5.3 主题设置:让老版本工具也有新面孔
PySimpleGUI 4.60.5自带很多主题色,可以用sg.theme("DarkBlue3")切换。我一般喜欢用DarkTeal9或SystemDefault。如果想让工具看起来专业一点,可以这样:
sg.theme("DarkBlue3")主题的设置在sg.Window创建前调用,组件颜色会自动跟着变。这一点在给同事交付工具时特别重要——用默认灰色主题的工具,同事总觉得是临时写的脚本;换一个好点的主题,瞬间就有了“正式软件”的气质。
5.4 打包成exe时的注意事项
PySimpleGUI写的脚本最终肯定要打包给别人。我用的打包命令是:
pyinstaller --onefile --windowed --add-data "theme.json;." file_tidy.py注意--onefile会把所有依赖塞进一个exe,但启动速度会慢一些。--windowed是防止控制台黑框弹出来。如果你用了图片、图标资源,记得用--add-data带上。
在这个版本下遇到过一个问题:PyInstaller打包后用--windowed模式,print输出内容看不到,影响排错。所以打包前建议先跑一个控制台版本,确认逻辑没问题再打windowed版本。
6. 避坑指南:4.60.5的常见坑和解决办法
6.1 事件循环里更新控件导致崩溃
这是PySimpleGUI新手最容易踩的坑。主循环while True里面,如果你想根据某个事件动态修改界面内容,不能直接用window["-KEY-"].update(...),会偶尔出现“Window closed”之类的运行时错误。正确做法是:先判断event,再更新,最后调用window.refresh()或者让循环自然返回。
if event == "-BUTTON-": window["-TEXT-"].update("已点击") window.refresh()6.2 多线程访问界面控件
刚才提到用write_event_value解决线程通信问题。另一个常见做法是:
def worker(window): for i in range(10): time.sleep(1) window.write_event_value("-UPDATE-", i) threading.Thread(target=worker, args=(window,), daemon=True).start()在主循环里:
if event == "-UPDATE-": window["-PROGRESS-"].update_bar(values[event])这样处理长任务时,窗口始终能保持响应,进度条也能正常滚动。
6.3 获取多个输入值时的小技巧
当窗口里有很多sg.Input时,values字典的key结构是(行号, 列号),非常不好记。更合理的做法是给每个输入框指定明确的key,例如key="-NAME-"、key="-PHONE-"。这样不仅在代码里可读性好,而且在界面调换位置时,不用去改业务逻辑。
6.4 目录不存在时程序直接崩溃
用os.listdir读取一个不存在的文件夹,会直接抛异常。除了用try...except捕获以外,还可以在“打开浏览窗口”的时候直接限制用户只能选择已存在的目录,但用户仍然可能在路径输入框里手动改。所以最稳妥的做法还是多做一步判断:
if not os.path.exists(folder): sg.popup("文件夹不存在,请重新选择") continue6.5 打包后杀毒软件误报
PyInstaller打包的exe在部分Windows电脑上会被Windows Defender查杀,这是因为--onefile模式会把所有代码解压到temp目录再运行,这种动态行为容易被误判。解决办法是:升级代码签名(付费)、改用--onedir模式打包,或者在杀毒软件里加白名单。对内部工具来说,加白名单是最省事的。
7. 有哪些老版本资源值得存一份:离线包、示例代码、文档快照
既然网上有人专门找“PySimpleGUI-4.60.5老版本免费.zip”,说明很多人还是希望本地有一份备用资源。我个人的习惯是,每次部署前,把以下文件保存到一个固定的代码仓库里:
- PySimpleGUI 4.60.5的whl包
- PyInstaller的spec配置
- 常用主题配置文件
- 一段基础模板代码
这样换电脑、换环境时,不用重新去翻官网。
7.1 官方文档离线版
PySimpleGUI的文档网站内容很丰富,但中文用户直接看英文文档有时比较吃力。4.60.5年代的中文教程相对齐全,我在博客上整理过一份,涵盖窗口布局、事件循环、组件属性速查。后来为了方便其他同事,我把常用组件的API做了一个速查表,这里也列出来一部分,方便你直接抄。
| 组件名称 | 常用参数 | 说明 |
|---|---|---|
| sg.Text | text, size, font | 显示静态文本 |
| sg.InputText | default_text, key | 单行文本输入 |
| sg.Multiline | default_text, size, key | 多行文本输入 |
| sg.Button | button_text, key | 按钮 |
| sg.Listbox | values, size, select_mode, key | 列表选择 |
| sg.DropDown | values, default_value, key | 下拉菜单 |
| sg.Checkbox | text, default, key | 复选框 |
| sg.Radio | text, group_id, default, key | 单选框 |
| sg.Slider | range, default_value, orientation, key | 滑块 |
| sg.Image | filename, data, key | 图片显示 |
| sg.ProgressBar | max_value, size, key | 进度条 |
| sg.Output | size, key | 日志输出 |
7.2 整理一个可复用的模板文件
下面是我开工一个新工具时最常用的模板,直接保存为app.py,改改布局就能用:
import PySimpleGUI as sg sg.theme("DarkBlue3") def build_layout(): layout = [ [sg.Text("欢迎使用通用工具", font=("微软雅黑", 16, "bold"))], [sg.Text("输入内容"), sg.InputText(key="-INPUT-")], [sg.Button("执行"), sg.Button("退出")], [sg.Output(size=(80, 10), key="-OUTPUT-")] ] return layout def main(): window = sg.Window("通用工具", build_layout()) while True: event, values = window.read() if event in (sg.WIN_CLOSED, "退出"): break if event == "执行": text = values["-INPUT-"] print(f"你输入了: {text}") window.close() if __name__ == "__main__": main()这个模板虽然简单,但已经包含了主题、布局构造、事件循环、输出区几个关键部分。遇到新需求,往build_layout里加组件,在事件循环里加分支就行,五分钟就能搭出一个能用的工具。
8. 从4.60.5到最新版:如果真要迁移,需要注意什么
虽然我推荐在旧项目里继续用4.60.5,但如果你哪天必须迁移到新版,有几个地方需要重点检查。
8.1 接口变动的方向
新版的sg.Window对resizable和finalize的行为更严格,以前不显式设置resizable=True、但可以拖动的窗口,新版默认固定大小。另外,sg.Text的justification参数在新版里被改成justify,虽然旧参数还有兼容层,但控制台的DeprecationWarning会一直刷。
8.2 事件循环的改变
新版对事件循环的执行顺序有调整,某些在旧版里不刷新也能自动重绘的场景,在新版里必须手动window.refresh()。迁移以后,最大的工作量不是在改控件,而是到处补刷新逻辑。
8.3 怎么用一个虚拟环境保留老版本
最简单的做法是给每个项目建独立虚拟环境。项目A用Python 3.7 + PySimpleGUI 4.60.5,项目B用Python 3.10 + 新版PySimpleGUI,互不干扰。用requirements.txt锁定依赖版本:
python -m venv venv_old venv_old/Scripts/activate # Windows pip install PySimpleGUI==4.60.5这样新老项目并存,完全不会冲突。如果你手上同时在维护好几个这类老版本GUI工具,强烈建议全部迁到虚拟环境,省得以后系统环境一乱,整个机器上的Python项目全部跑不了。
8.4 当新项目接手老代码时
接手别人写的PySimpleGUI老项目,第一步不是直接跑,而是先全局搜索sg.SetOptions、sg.ChangeLookAndFeel、sg.PopupGetText这些旧式写法。4.60.5的写法如果直接扔到新版环境运行,十有八九会在启动第二行就抛AttributeError。先把这些接口改为对应的新写法,再考虑其他功能优化。
# 旧写法(4.60.5及之前) sg.ChangeLookAndFeel('DarkBlue3') # 新写法 sg.theme('DarkBlue3')9. 一些实际案例:用4.60.5做的那些小工具
最后聊聊这款老版本在我实际工作里做过的几个东西,希望能给你一些灵感。
9.1 Excel批量模板生成器
销售部同事每个月要填几十份格式相同的报价单,手工复制效率低。我写了一个工具,窗口左边是客户列表,右边是报价单预览,点“生成”后自动用openpyxl填充模板,并保存到“待发送”文件夹。整个界面不到100行,功能稳定运行了半年多,只有一次因为销售更新了模板格式文件,微调过字段映射。
9.2 内部数据库查询面板
之前给数据团队做过一个SQL查询工具,支持输入SQL、选择数据库连接、展示查询结果表格,并用sg.Table分页显示。这个工具用的sg.Table模式在4.60.5里很稳定,数据量在几千行内响应很快。直到后来数据量增长到几万行,我们才迁移到独立的数据可视化方案。
9.3 图片批量压缩与重命名工具
这个是用PySimpleGUI加Pillow做的。窗口拖入一批图片,统一进度条走完,自动压缩到指定大小并重命名。当时是为了处理一批活动物料图,压缩比设成80%,文件体积平均减小了一半。这里有个值得提的经验:Pillow处理图片是CPU密集操作,如果图片特别多,也要放到子线程里处理,否则窗口卡住会让用户误以为程序崩了。
这些例子说明,PySimpleGUI 4.60.5虽然是老版本,但它能覆盖绝大多数内部工具、自动化辅助、可视化小工具的需求。界面不够惊艳,但开发效率极高,出了问题也很容易排查。如果你也是一个人在项目工位上写脚本、做自动化的那种开发者,这个版本确实值得长期留着用。
本文还有配套的精品资源,点击获取