我有一个学生提交了这样的函数:
def infinite_windows():
window = tkinter.Tk()
infinite_windows()
我已经在 try- except 块内测试了一些东西。 我的代码报告了 RecursionError,但下次它要求用户输入时它会冻结我的桌面,我必须终止 Python。 以下代码挂起,但仅当包含 input() 调用时:
import tkinter
def infinite_windows():
window = tkinter.Tk()
infinite_windows()
try:
infinite_windows()
except Exception as e:
print("caught the exception!")
print(e)
input("hi there") #hangs here
有什么方法可以让我处理这种行为并继续运行 Python,而不删除对 input() 的调用?
我将此作为可能的解决方案:
import tkinter
def infinite_windows():
window = tkinter.Tk()
infinite_windows()
# Store all Tk objects in an array
_all_windows = []
class _Tk(tkinter.Tk):
def __init__(self, *args, **kwargs):
_all_windows.append(self) # Add this Tk object in the array
super().__init__(*args, **kwargs)
tkinter.Tk = _Tk # Replace tkinter's Tk class with our own
try:
infinite_windows()
except Exception as e:
print("caught the exception!")
print(e)
for window in _all_windows:
try:
window.destroy()
except tkinter.TclError:
# If the window wasn't fully created/already was destroyed
pass
_all_windows.clear() # Clear the array
input("? ")
基本上,我用继承自
tkinter.Tk
的我自己的类覆盖 tkinter.Tk
(不会导致递归问题,因为我的类是在替换 tkinter.Tk
之前构建的)。在我自己的班级中,我跟踪全局列表中的所有 tkinter.Tk
对象并在最后销毁它们。
这种方法有效(在带有 Wayland 的 Ubuntu 上),但有一些限制:
tkinter.Tk
对象所需的 1.9 GB RAM。我们对此无能为力,因为 python 不愿意将 RAM 释放回操作系统tkinter.Tk
类的操作,则此方法不起作用:import tkinter
def infinite_windows(window_class=tkinter.Tk):
window = window_class()
infinite_windows()
要解决该问题,您可以将覆盖
tkinter.Tk
的代码移到学生代码之前(但如果学生尝试从 __future__
导入某些内容,则会引发错误)