实际上,这并不是在这里重要的交互式解释器,而是在TTY上等待输入。您可以从如下脚本中获得相同的行为:
import tkinter
t = tkinter.Tk()
input()
(在Windows上,您可能必须在pythonw.exe中而不是python.exe中运行该脚本,但是否则,您不必执行任何特殊操作。)
那么它是怎样工作的?最终,诀窍归结为PyOS_InputHook
-readline
模块工作的方式相同。
如果stdin是TTY,则每次它尝试使用input()
,code
模块的各个位,内置REPL等来获取一行时,Python都会调用已安装的任何内容,PyOS_InputHook
而不仅仅是从stdin中读取。
它可能更容易理解什么readline
呢:它试图select
在标准输入或类似,循环为每个输入新的字符,或每0.1秒或每一个信号。
什么Tkinter
确实是相似的。因为它必须处理Windows,所以它更加复杂,但是在* nix上,它的行为与相似readline
。除了Tcl_DoOneEvent
每次在循环中都在调用。
这就是关键。Tcl_DoOneEvent
重复调用与执行完全相同mainloop
。
(线程使一切变得更复杂,当然,但是让我们假设你还没有创建任何后台线程。在你真正的代码,如果你想创建后台线程,你只需要一个线程所有的Tkinter
东西,上街区mainloop
反正, 对?)
因此,只要您的Python代码将大部分时间都花在了TTY输入上(就像交互式解释器通常那样),则Tcl解释器会不断变化,而GUI也会响应。如果您在除TTY输入之外的其他位置上使Python解释器块阻塞,则Tcl解释器未运行,并且您的GUI没有响应。
如果您想在纯Python代码中手动执行相同的操作怎么办?如果您想例如将Tkinter GUI和select
基于网络的客户端集成到单线程应用程序中,就需要这样做,对吗?
您可以select
设置0.02s的超时(默认输入挂钩使用相同的超时),并在t.dooneevent(Tkinter.DONT_WAIT)
每次循环中调用。
或者,您也可以通过致电来让Tk开车mainloop
,但是请使用after
和朋友来确保您select
经常打电话。