Spyder环境下Tkinter mainloop无法终止的问题及解决咨询
Spyder中Tkinter脚本关闭窗口后无法继续执行代码的问题
环境
- Python 3.9
- Spyder 3.9.13
问题现象
基础脚本表现
运行以下代码:
import tkinter as TK ws=TK.Tk() print('Foo') ws.mainloop() print('Bar')
- 命令行:关闭窗口后正常打印
Bar - Spyder:仅打印
Foo,窗口关闭后脚本卡住,不执行后续代码
添加Exit按钮后的表现
import tkinter as TK ws=TK.Tk() TK.Button( ws, text='Exit', command=lambda:ws.destroy() ).pack(expand=True) print('Foo') ws.mainloop() print('Bar')
- Spyder中点击Exit按钮,仍不打印
Bar - 若将
destroy()替换为quit(),会打印Bar但窗口无法关闭
类封装后的部分解决
import tkinter as TK class FooBar: def __init__(self,Name): self.win=TK.Tk() self.win.title = Name def terminate(self): self.win.quit() self.win.destroy() ws=FooBar('FooBar') TK.Button( ws.win, text='Exit', command=lambda:ws.terminate() ).pack(expand=True) print('Foo') ws.win.mainloop() print('Bar')
- 命令行:无论点击Exit按钮还是窗口叉号,都会打印
Bar - Spyder:仅点击Exit按钮会打印
Bar,点击窗口叉号仍卡住
原因分析
Spyder的IPython内核会对Tkinter的事件循环做特殊处理:默认情况下,当通过窗口叉号关闭主窗口时,Spyder并未真正终止mainloop(),只是将窗口隐藏,导致脚本停留在mainloop()调用处,后续代码无法执行。而单独调用quit()只会终止事件循环但不销毁窗口,单独调用destroy()仅销毁窗口但无法让Spyder感知到事件循环结束。
解决方法
方法1:修改Spyder的图形后端设置
- 打开Spyder,依次点击
Tools > Preferences - 进入
IPython Console > Graphics选项卡 - 将Backend设置为
Tkinter(不要选Automatic或Inline) - 重启Spyder后,Tkinter脚本的行为会和命令行一致
方法2:绑定窗口关闭事件并同时执行quit和destroy
给主窗口绑定WM_DELETE_WINDOW事件,确保关闭窗口时同时终止事件循环并销毁窗口:
import tkinter as TK ws = TK.Tk() def on_closing(): ws.quit() ws.destroy() # 绑定窗口叉号关闭事件 ws.protocol("WM_DELETE_WINDOW", on_closing) # 按钮也调用同一个关闭函数 TK.Button(ws, text='Exit', command=on_closing).pack(expand=True) print('Foo') ws.mainloop() print('Bar')
这样无论通过窗口叉号还是Exit按钮关闭,都能正常执行mainloop()后的代码。
内容的提问来源于stack exchange,提问作者Crowley
相关产品推荐
相关产品推荐

