Thonny 这个 IDE 在 Python 教学和嵌入式入门圈子里出场率极高,界面干净、调试直观、装完就能跑,是很多人给零基础学员和单片机新手推荐的第一选择。但只要你用过一段时间就会发现,它的欢迎页或者工具栏上挂着一个第三方的外部链接图标,社区里一般直接管它叫那个彩色旗标按钮。这个图标本身不影响功能,可是在做教学截图、录屏演示、批量装机、或者把 Thonny 打包进自己课程镜像的时候,它就有点碍事了——截图不整齐、学员好奇心重、点进去跳转到外部页面还得重复解释。所以「Thonny 去掉图标」这件事,本质上不是功能问题,而是一个界面定制和发行版裁剪的工程问题。下面这套东西,我会从怎么定位这个图标、它有几种改法、每种改法的利弊,一直讲到实际动手的完整流程和踩过的坑,适合三类人看:一是做教学环境统一部署的老师,二是想把 Thonny 揉进自己工具链的嵌入式玩家,三是单纯有界面洁癖、想让自己每天面对的编辑器清爽一点的人。
1. 先弄清楚你要动手的地方到底是什么
很多人一上来就去搜"怎么删掉 Thonny 那个按钮",搜到的答案五花八门,有的让你删图片,有的让你改源码,有的让你写插件,看完了更懵。原因很简单:这个图标在不同 Thonny 版本、不同安装方式下,出现的位置和实现方式是不一样的。你照着别人的教程改,改的是 A 位置,你的版本里图标在 B 位置,那当然没效果。
1.1 Thonny 的界面不是一张图,是一堆零件拼出来的
Thonny 是纯 Python + tkinter 写的,这一点决定了它的界面天生就是"可拆"的。整个主窗口由thonny/workbench.py里的 Workbench 类搭建骨架,菜单栏、工具栏、编辑区、变量面板、Shell 区,各管各的。工具栏上的每一个按钮、欢迎页上的每一行文字和链接,背后都是一段创建 widget 的代码。
图标本身是位图资源,一般是 PNG 或者 GIF,放在安装目录的thonny/res/下面;而"什么时候显示这个图标""点它干什么"是逻辑,写在对应的.py文件里。这就意味着你有两条路可以走:要么干掉资源文件让它加载不出来,要么干掉创建逻辑让它压根不被创建。两条路的稳定性和副作用完全不同,后面第三章会详细拆。
这里先建立一个认知:你在界面上看到的一个小图标,在代码层面至少牵扯三个东西——资源文件路径、加载资源的代码、把这个 widget 放进布局的代码。三者缺一,图标都不会正常显示出来。理解了这一点,你就知道为什么有时候删了图片它还显示(因为缓存或打包进去了),有时候删了图片界面会报错(因为加载失败没做异常处理)。
1.2 三种诉求,对应三种改法,别混着用
我接触过的需求基本能归成三类,改法差别挺大,先对号入座:
| 诉求类型 | 典型场景 | 推荐改法 | 关键约束 |
|---|---|---|---|
| 一次性清干净 | 自己电脑上看着顺眼 | 资源替换法 | 升级会还原,需重复操作 |
| 长期稳定可用 | 教学机房、批量装机 | 源码注释法 | 需固定版本,禁止自动升级 |
| 不动官方文件 | 多人共用、无管理员权限 | 外挂插件法 | 依赖插件加载机制,版本差异大 |
| 对外分发 | 打包成 exe 或课程镜像 | 打包前裁剪法 | 必须在打包前改,改完再打包 |
这张表我建议你截图存一下。因为很多人失败的根本原因,就是用"一次性"的方法去干"长期"的活——比如在教学机房里只替换了图片,结果某次 Thonny 自动更新,图标又回来了,一个班五十台机器重新来一遍,非常折腾。
还有一种情况要单独说:你的 Thonny 是通过 pip 装的,还是官网下载的 Windows 安装包,还是便携版解压目录。这三者的文件布局不一样:
- pip 安装:代码在 Python 的
site-packages/thonny/里,和你的其他第三方库混在一起; - Windows 安装包:一般在
C:\Program Files (x86)\Thonny\或者用户目录下的 AppData 里,自带一个独立的 Python 运行时; - 便携版:解压到哪就在哪,最干净,改起来最方便,也最适合做批量分发。
所以动手前第一件事,先确认你手上这份东西的"身份"。这个动作花不了两分钟,但能省掉后面一大半的无效尝试。
2. 精准定位:三分钟找到那个图标对应的代码
定位是整件事里技术含量最高、也最容易被跳过的一步。跳过它的结果就是瞎改,改完不知道为什么不生效。下面这套流程是我自己反复用过的,基本三分钟内能锁定目标。
2.1 第一步:让 Python 自己告诉你 Thonny 在哪
别靠猜路径,直接问解释器。开一个命令行,输入:
python -c "import thonny, os; print(os.path.dirname(thonny.__file__))"输出那一行就是 Thonny 包的绝对路径。如果是 Windows 安装包版本,注意要用它自带的那个 python,不是你系统里的。安装包版一般在安装目录下有个python.exe或者bin\python.exe,用完整路径调用就行:
"C:\Program Files (x86)\Thonny\python.exe" -c "import thonny, os; print(os.path.dirname(thonny.__file__))"这一步得到的路径,后续所有操作都以它为基准。如果你打印出来的路径有两个(比如系统 Python 里一个、Thonny 自带的一个),那说明你机器上装了两份 Thonny,这一点非常关键,第 5 章有个大坑就源于此。
2.2 第二步:翻目录,看清楚资源区和代码区的分工
进入上一步得到的目录,你会看到一个典型的 Python 包结构。这里挑几个和界面定制强相关的说:
res/或resources/:所有图片、图标、主题文件。你打开看一眼文件名,基本就能猜到哪个图标是干什么用的,命名都挺直白。plugins/:Thonny 的插件目录,欢迎页、Shell、变量面板这些功能模块都在这里面,一个功能一个文件。workbench.py:主窗口的搭建逻辑,工具栏按钮就是在这里创建的。misc_utils.py、common.py、ui_utils.py:公共工具函数,资源路径拼接、widget 查找之类的辅助函数常在这几个文件里。
在命令行里快速扫一眼资源目录:
ls res | head -60或者在 Windows 下:
dir res看到可疑的图标文件先别急着删,记下文件名,这是后面检索代码的线索。
2.3 第三步:用检索命令锁定引用点
拿到资源文件名之后,反过来搜谁在引用它。Linux 和 macOS 下:
grep -rn --include=*.py -i "关键词" .Windows 下用 findstr:
findstr /s /i /m /c:"关键词" *.py那个"关键词"填什么?如果你已经知道资源文件名,就填文件名去掉后缀的部分;如果不确定,可以填几个通用词试试,比如donate、support、banner、link、welcome这类和外部链接、捐赠、欢迎页相关的英文词。我一般会先用欢迎页的模块名搜一遍,因为这类图标绝大多数情况下是挂在欢迎页上的:
grep -rn --include=*.py "Welcome" plugins/结果会告诉你哪个文件里创建了欢迎页上的那些控件。打开那个文件,往下翻,通常能看到类似ttk.Button(...)或者ttk.Label(...)配合一个图片参数的代码块。找到那一行,你就找到了要动手的位置。记住行号,下一步用得上。
注意:检索的时候一定要确认自己是在第 2.1 步打印出来的那个目录里操作。在不同目录里搜,搜出来的引用点可能是另一个副本的,改完当然不生效。
3. 四种落地改法,按侵入性从低到高排
定位完成之后,怎么改就是选择题了。我把四种方法按"对官方文件的侵入程度"从小到大排,你可以根据自己的场景挑。每种方法我都写清楚适用条件和副作用,别只看哪个人气高。
3.1 资源替换法:五分钟搞定,但治标不治本
思路最简单:图标不显示了,本质上就是那个图片文件加载不出来或者加载出来是透明的。所以你可以直接把那个 PNG 替换成一个 1x1 的透明图片,或者干脆改名备份走,让加载失败。
具体做法:先备份原始图标文件,然后生成一个 1x1 的透明 PNG 覆盖过去。用 Python 两行就能生成:
import base64 data = base64.b64decode("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==") open("res/替换的目标文件名.png", "wb").write(data)我实测下来,这个方法的成功率大概七成左右,失败的那三成主要是两个原因:一是图标在代码里用了PhotoImage缓存,同名文件被内存里缓存的旧图占着,你换了文件也没用;二是留下了一个看不见但占位的空白区域,布局上会莫名其妙多出一块空白,截图看着更别扭。
优点是快,不用改一行代码,出问题把备份文件拷回去就还原了。适合"我就想今天截图干净一点"这种临时需求。长期用、批量用,不推荐。
3.2 源码注释法:稳定性最好,前提是锁死版本
这是我给教学机房做镜像时的首选。做法就是在第 2.3 步定位到的那个文件里,把创建图标的代码段注释掉。一般长这样:
# 原始代码大概是这样 self.link_button = ttk.Button( self, text="xxx", image=self.some_icon, command=self._open_link, ) self.link_button.grid(row=3, column=0, sticky="w")你把整个创建和布局的部分都用#注释掉,或者更干脆一点,直接删掉这两段。保存,重启 Thonny。
这个方法的关键不是改代码,而是改完之后必须清掉__pycache__。Python 会把编译好的字节码缓存起来,你改了.py但缓存还在,跑起来用的还是旧的逻辑。清理命令:
find . -name "__pycache__" -type d -exec rm -rf {} +Windows 下手动去目录里把所有__pycache__文件夹删掉就行。
副作用要提前说清楚:如果你注释的是按钮创建代码,但别的地方还有代码引用这个按钮对象(比如某个事件回调里self.link_button.configure(...)),那启动时就会抛AttributeError。所以注释之前,先在这个文件里搜一遍这个变量名的所有出现位置,全部处理干净。这个坑我踩过,Thonny 启动直接白屏,看日志才发现是回调引用了不存在的控件。
3.3 外挂插件法:不碰官方文件,适合多人共用环境
如果你的 Thonny 在公共机器上,或者你不想承担改坏官方文件的风险,那就走插件这条路。Thonny 支持从用户配置目录加载自定义插件,这个机制是内置的,不需要你动安装目录里的任何东西。
用户插件目录的位置:
- Windows:
%APPDATA%\Thonny\plugins - Linux:
~/.config/Thonny/plugins - macOS:
~/Library/Application Support/Thonny/plugins
目录不存在就自己建一个,然后在里面放一个.py文件,写一个继承ThonnyPlugin的类,在合适的生命周期钩子里去遍历控件树,把目标控件销毁掉:
from thonny import get_workbench from thonny.plugins import ThonnyPlugin def walk(widget): yield widget for child in widget.winfo_children(): yield from walk(child) class CleanUiPlugin(ThonnyPlugin): def load(self): wb = get_workbench() # 事件名请以你本地版本的调用为准,常见的是 WorkbenchReady wb.bind("WorkbenchReady", self._on_ready, True) def _on_ready(self, event=None): wb = get_workbench() for widget in walk(wb): # 按类名和文本特征筛选,具体特征按你版本调整 if widget.winfo_class() == "TButton": text = "" try: text = str(widget.cget("text")) except Exception: pass if "关键词" in text: widget.destroy()这段代码的核心是那个walk函数,深度优先遍历整个 tkinter 控件树。它不依赖具体版本的文件结构,只要控件还在,就能被找到。缺点是筛选条件得你自己对着实际界面调,因为不同版本那个按钮的类名和文本可能不一样。我一般的调试办法是先写个临时的遍历脚本,把所有 TButton 的文本打印出来,一眼就能认出来哪个是要干掉的那个。
这个方法的稳定性取决于 Thonny 的插件加载机制有没有变。我用过几个版本都还能跑,但不能保证未来一直有效。它的最大价值是"可随时撤掉"——把那个.py文件删了,世界立刻恢复原样。
3.4 打包前裁剪法:对外分发唯一正确的姿势
如果你是要把 Thonny 打包进课程镜像、或者做成一个 exe 发给学员,那前面三种方法都得往后排一排。因为打包动作会把当时目录里的所有东西固化进去,你打包完了再去改源文件,对已经生成的产物没有任何影响。
正确顺序是:先按 3.2 或 3.1 的方法把源目录改好,清理掉__pycache__,启动一次确认界面干净了,然后再执行打包。用 PyInstaller 的话,注意资源目录要一起带上:
pyinstaller --noconfirm --windowed ^ --add-data "thonny/res;thonny/res" ^ --name Thonny-Custom ^ 你的入口脚本.pyWindows 下路径分隔符是分号,Linux 和 macOS 下是冒号,这个搞错了资源就丢,界面上的图标全变问号或者干脆不显示。打包完先在一台干净的机器上跑一遍验收,别只在自己开发机上试——开发机上装了一堆依赖,很多问题会被掩盖掉。
4. 完整实操记录:从备份到验证
上面讲的是方法论,这一章我把一次完整的实操过程记下来,你可以照着走一遍。我选的是源码注释法,因为它最能说明问题,其他方法都是在它基础上做加减。
4.1 环境准备与备份
先确认版本,别改了半天发现版本对不上教程:
python -c "import thonny; print(thonny.__version__)"记下这个版本号。然后在同目录下建一个备份文件夹,把你要动的文件先拷一份:
mkdir _backup cp plugins/欢迎页对应文件.py _backup/我更推荐的做法是整个thonny目录压一个 zip 存起来,几百 MB 而已,出问题直接解压覆盖,比一个个文件回滚靠谱得多。尤其是给机房做镜像的时候,备份这一步绝对不能省,因为你在自己机器上验证通过的东西,到了五十台不同配置的机器上,什么奇怪问题都可能冒出来。
4.2 动手改欢迎页上的那个控件
打开第 2.3 步定位到的文件,通常能看到一个类,里面有个_create_ui或者类似名字的方法,负责把欢迎页上的所有元素摆上去。结构大致是:先建一个 Frame,然后往里塞 Label、Button、链接文本。
找到创建那个图标的几行,注释掉。同时检查三件事:
- 有没有别的地方引用了这个控件变量名,一并处理;
- 这个控件被注释掉之后,它占的那一行或那一列的布局会不会塌掉(比如用了
grid的rowspan,少一个控件整个错位); - 注释完之后,那个位置是不是留下了一块空白,需不需要顺手把下面的控件上移一行。
第 3 点特别容易被忽略。你有两种处理方式:一是把后面的控件行号往上调一位,二是保留控件的网格位置,但把控件本身换成空的ttk.Frame占位。前者更干净,后者更省事、风险更低。我在教学环境下一般选后者,因为改行号容易牵一发动全身,尤其是布局代码里有动态计算行号的地方。
4.3 工具栏图标的处理要单独看
工具栏上的按钮是在workbench.py里建的,逻辑通常是遍历一个配置列表,循环创建按钮。这种写法下,你要删的就不是"某一行",而是"列表里的某一项"。找到那个列表,把对应项去掉就行,比删代码行更安全,因为循环逻辑本身不动。
如果工具栏按钮的图标和欢迎页共用同一张图,那你改完工具栏还得回头看看欢迎页有没有受影响。共用资源是这类定制里最常见的连带问题,动手前先用检索命令确认一下这张图被引用了多少次:
grep -rn --include=*.py "图标文件名" .引用点超过一处的,就得每个点都考虑一遍。
4.4 验证清单与回滚
改完之后,别只看一眼主窗口就完事。下面这份清单我每次都会过一遍:
- 冷启动(完全退出再打开)后图标是否消失;
- 欢迎页其他链接、按钮是否还能正常点击;
- 工具栏按钮是否还对齐,没有出现空白断层;
- 打开新建文件、运行一个简单脚本,确认核心功能没被影响;
- 打开"工具 - 选项",确认设置面板能正常弹出;
- 切换主题(如果有),看图标消失后有没有留下色块。
任何一条不过,立刻回滚。回滚就是把_backup里的文件拷回去,删掉__pycache__,重启。千万不要在出问题的状态下继续叠加修改,你会分不清是哪一个改动引入的问题。
5. 踩坑实录与问题速查
这一章是我个人踩过的坑和帮别人排查过的案例汇总,价值可能比前面所有章节加起来都高,因为这些问题在官方文档里一个字都不会写。
5.1 改完没反应?先按这四类原因逐个排除
第一类:机器上有两份 Thonny。你改的是 A 目录,实际启动的是 B。验证方法:改完之后在文件里故意加一行语法错误,如果启动 Thonny 报错了,说明你改对了地方;如果照常启动,说明你根本改的不是它加载的那一份。这个方法有点暴力,但特别好用。
第二类:__pycache__没清。前面说过很多次了,但实际排查里这仍然是出现频率最高的原因。养成习惯:改完.py顺手清缓存。
第三类:控件是动态创建的。有些界面元素不是启动时就建好的,而是等你切到某个标签页、或者点了某个菜单才生成。这种情况下你改创建代码是有效的,但如果你的验证方式是"启动后看主页",那你看不到变化是因为它本来就还没生成。验证时要把所有相关页面都点一遍。
第四类:图标走了网络加载或者主题包。少数情况下图标不是从本地res目录读的,而是通过主题配置映射过来的。这时候你要找的不是图片文件,而是主题配置文件里的映射项。这种相对少见,但如果前三类都排除了还是没效果,就往这个方向查。
5.2 界面报错和布局异常的典型表现
改完之后 Thonny 启动直接白屏、或者弹出报错对话框,八成是引用了不存在的控件。看报错信息里的行号,顺着找过去,一般是某个configure或者bind调用引用了被你注释掉的变量。
界面上出现异常的空白块、控件错位、窗口大小不对,一般是布局没补偿。tkinter 的grid和pack对缺件很敏感,删一个控件可能让整行塌陷。处理原则前面说过:优先用空占位控件替代,而不是真的删掉。
还有一种诡异情况:图标不见了,但鼠标移到原来位置还能点,点下去还会跳转。这是典型的事件绑定残留——控件被隐藏了但没销毁,绑定还在。解决办法是用destroy()彻底销毁控件,而不是用pack_forget()或者grid_remove()只把它藏起来。这两个方法的区别是:藏起来还在内存里、还响应事件;销毁了就真没了。你要的是后者。
5.3 升级、打包、多用户场景的三个大坑
升级覆盖:pip 装的 Thonny,一次pip install -U thonny就把你改的东西全冲掉了。所以长期方案一定要配合版本锁定,比如在教学镜像里明确写死版本号。用 pip 的话可以这样:
pip install thonny==4.x.x打包后失效:现象是在开发机上好好的,打包出来的产物图标又回来了。原因通常是打包时把改之前的文件收集进去了,或者打包工具缓存了旧的资源。解决办法是打包前清一次build和dist目录,再重新打。
多用户权限:Windows 的安装包版装在Program Files下,普通用户没有写权限,你改了文件保存会失败,但有些编辑器会默默失败不报错。用管理员权限打开编辑器再改,或者干脆用便携版做定制分发。
5.4 问题速查表
| 现象 | 最可能的原因 | 处理动作 |
|---|---|---|
| 改完完全没变化 | 改错副本 / 缓存未清 | 语法错误验证法 + 清__pycache__ |
启动报AttributeError | 注释了仍被引用的控件 | 搜变量名,处理所有引用点 |
| 图标消失但还能点 | 只隐藏未销毁 | 改用destroy() |
| 布局错位或空白块 | 布局未补偿 | 用空 Frame 占位 |
| 升级后图标回来了 | 官方文件被覆盖 | 锁版本,或用用户插件法 |
| 打包产物图标仍在 | 打包前未改 / 缓存 | 清 build/dist 重打 |
| 保存文件时静默失败 | 目录无写权限 | 管理员权限或用便携版 |
这张表打印出来贴在工位上都不为过,改界面的事情来来回回就是这些。
6. 顺带聊聊 Thonny 界面定制在嵌入式与教学场景里的用法
把这件小事往大一点说,它其实是一个"工具链定制"的缩影。我接触 Thonny 最多的两个场景,一个是教学,一个是 ESP32 这类开发板的入门开发,这两个场景对界面定制的需求都很具体。
6.1 批量装机时界面统一比功能统一更重要
教学环境里,五十台机器如果界面各不相同,讲课的时候光"点左上角那个按钮"这一句话就得分好几种说法描述。所以我做镜像的时候会把 Thonny 的欢迎页、工具栏统一裁剪一遍,把跟课程无关的入口全部清掉,只留运行、停止、单步这几个核心按钮。学员的注意力是极其有限的,界面上多一个陌生的图标,就多一次被点开的机会。
批量装机的关键在于可重复。我的做法是把裁剪好的thonny目录整个打包,配一个安装脚本,装机时解压到固定路径,然后写一个启动快捷方式指向它自带的 python。不要用 pip 在线安装,网络环境一有波动,五十台机器里总有几台装不上或者版本不一致,后面排查起来非常痛苦。
6.2 开发板场景下,把界面让给 Shell 和文件树
用 Thonny 玩 ESP32 系列开发板的人越来越多,典型流程是:连上板子,通过 Shell 看串口输出,用文件面板往板子里传脚本。这种场景下,你对主编辑区的依赖其实没那么强,反而是 Shell 区的显示空间和专业入口更重要。
我自己会做的几件事:把不需要的入口全部去掉,减少误点;把 Shell 区的字体调大,方便长时间盯串口日志;把文件面板固定在顺手的位置。当你在调一块接了小屏幕的开发板、反复上传脚本看效果的时候,界面上每一个多余的像素都在消耗你的注意力。
这里有个实际经验:上传脚本失败的时候,第一反应不要怀疑脚本,先看 Shell 区有没有报错信息。很多时候是板子连接状态变了,或者串口被别的程序占着。把 Shell 区的可视面积留够,能帮你省下大量瞎猜的时间。
6.3 关于长期维护,我给你三条实话
第一条,任何对官方文件的修改都要有版本号意识。改之前记下版本,改之后在文件里加一行注释写上"本文件已被定制,基于 x.x.x 版本,升级前请重新应用"。三个月后你自己都不记得改过什么,这行注释能救命。
第二条,优先选可撤销的方案。用户插件法之所以我推荐给多人环境,就是因为它可撤销——删文件即可,不留痕迹。源码注释法虽然稳定,但一旦改乱了,回滚成本高。
第三条,别把界面定制当成一劳永逸的事。工具会更新,你的需求也会变,今天想删的东西明天可能又需要了。所以每次改动都留好备份和记录,把它当成一个需要持续维护的小工程,而不是一次性动作。
我个人在实际操作中的体会是,界面裁剪这件事,技术难度其实不高,难点全在"知道自己改的是哪一份、改完之后怎么验证、以及怎么让它在下一次更新后还活着"。把这三件事想清楚了,剩下的就是几分钟的手工活。另外分享一个我一直在用的小技巧:改完不要立刻大规模部署,先在一台机器上放两天,正常用一用,很多隐藏问题只有真正用起来才会暴露——比如某个菜单点进去崩溃、某个快捷键失效,这些在启动测试里根本发现不了。