tkinters mainloop 困住了我的 foo
tkinters mainloop has trapped my foo
我在这个网站上看到很多问题,人们问用户编写的代码,比如一个函数 foo
,可以在 tkinter 的 mainloop
中执行,例如 or 。存在两种选择:使用 after
方法,或使用线程。我想更多地了解 after
方法的实际工作原理。
更准确地说,受此 excellent article 的启发,其中给出了 Python 中 GIL 如何工作的非常高级的描述,我想知道更多 after
方法在 tkinter 的 mainloop
.
内部的 Python 解释器处理 foo
方面起作用
当我使用 after
插入代码时,我特别困惑 CPython 解释器如何逐步执行代码。 foo
是如何被 tkinter 的 mainloop
执行的?
到目前为止我发现了什么:
Bryan Oakley,引自第一个 link,他说:"after does not create another thread of execution. Tkinter is single-threaded. after merely adds a function to a queue."
但是检查源代码
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""
if not func:
# I'd rather use time.sleep(ms*0.001)
self.tk.call('after', ms)
else:
def callit():
try:
func(*args)
finally:
try:
self.deletecommand(name)
except TclError:
pass
callit.__name__ = func.__name__
name = self._register(callit)
return self.tk.call('after', ms, name)
并没有真正帮助我,因为它没有揭示这些问题的答案,而且我是一名新手程序员,所以我真的不明白如何进一步追踪。
I'd like to know more about how the after method actually works.
mainloop
只是一个无限循环,它会扫描一些内部队列以查看是否有任何事件要处理。把它想象成是这样实现的:
def mainloop():
while the_window_exists():
if len(after_queue) > 0:
event = after_queue.pop()
if event.time_to_execute >= time.time():
event.command(**event.args)
if len(event_queue) > 0:
...
从字面上看,它并不是那样实现的——它的效率更高一些,而且还有更多的事情要做,但从逻辑上讲,它几乎是相同的。
当您调用 after
时,它只是将一些内容放入 "after" 队列。仅此而已。
使用相同的类比,after
可能会像这样实现:
def after(delay, code_to_run, *args):
event = Event()
event.code_to_run = code_to_run
event.args = args
event.time_to_execute = time.time() + delay
event_queue.append(event)
仅此而已。当您调用 after
时,您正在将某些内容放入队列中,而 mainloop
将内容从该队列中拉出。这一切都发生在同一个线程中。
对于mainloop
,您使用after
添加的函数与您移动鼠标或按下按钮时添加的函数没有什么不同——它只是一个队列中的事件对象.
我在这个网站上看到很多问题,人们问用户编写的代码,比如一个函数 foo
,可以在 tkinter 的 mainloop
中执行,例如after
方法,或使用线程。我想更多地了解 after
方法的实际工作原理。
更准确地说,受此 excellent article 的启发,其中给出了 Python 中 GIL 如何工作的非常高级的描述,我想知道更多 after
方法在 tkinter 的 mainloop
.
内部的 Python 解释器处理 foo
方面起作用
当我使用 after
插入代码时,我特别困惑 CPython 解释器如何逐步执行代码。 foo
是如何被 tkinter 的 mainloop
执行的?
到目前为止我发现了什么:
Bryan Oakley,引自第一个 link,他说:"after does not create another thread of execution. Tkinter is single-threaded. after merely adds a function to a queue."
但是检查源代码
def after(self, ms, func=None, *args):
"""Call function once after given time.
MS specifies the time in milliseconds. FUNC gives the
function which shall be called. Additional parameters
are given as parameters to the function call. Return
identifier to cancel scheduling with after_cancel."""
if not func:
# I'd rather use time.sleep(ms*0.001)
self.tk.call('after', ms)
else:
def callit():
try:
func(*args)
finally:
try:
self.deletecommand(name)
except TclError:
pass
callit.__name__ = func.__name__
name = self._register(callit)
return self.tk.call('after', ms, name)
并没有真正帮助我,因为它没有揭示这些问题的答案,而且我是一名新手程序员,所以我真的不明白如何进一步追踪。
I'd like to know more about how the after method actually works.
mainloop
只是一个无限循环,它会扫描一些内部队列以查看是否有任何事件要处理。把它想象成是这样实现的:
def mainloop():
while the_window_exists():
if len(after_queue) > 0:
event = after_queue.pop()
if event.time_to_execute >= time.time():
event.command(**event.args)
if len(event_queue) > 0:
...
从字面上看,它并不是那样实现的——它的效率更高一些,而且还有更多的事情要做,但从逻辑上讲,它几乎是相同的。
当您调用 after
时,它只是将一些内容放入 "after" 队列。仅此而已。
使用相同的类比,after
可能会像这样实现:
def after(delay, code_to_run, *args):
event = Event()
event.code_to_run = code_to_run
event.args = args
event.time_to_execute = time.time() + delay
event_queue.append(event)
仅此而已。当您调用 after
时,您正在将某些内容放入队列中,而 mainloop
将内容从该队列中拉出。这一切都发生在同一个线程中。
对于mainloop
,您使用after
添加的函数与您移动鼠标或按下按钮时添加的函数没有什么不同——它只是一个队列中的事件对象.