在不明显的情况下,它被称为 反应器,因为它反应
东西。循环是如何它的反应。
一次一行:
while True:
不是其实 while True;它更像while not loop.stopped。您可以调用reactor.stop() 来停止循环,并且(在执行一些关闭逻辑之后)循环实际上将退出。但它在示例中被描述为while True,因为当您编写一个长期存在的程序时(就像您经常使用 Twisted 一样),最好假设您的程序要么崩溃要么永远运行,并且“干净地退出”不是一个真正的选择。
timeout = time_until_next_timed_event()
如果我们稍微扩展一下这个计算,它可能更有意义:
def time_until_next_timed_event():
now = time.time()
timed_events.sort(key=lambda event: event.desired_time)
soonest_event = timed_events[0]
return soonest_event.desired_time - now
timed_events 是使用reactor.callLater 安排的事件列表;即应用程序要求 Twisted 在特定时间运行的功能。
events = wait_for_events(timeout)
这里的这一行是 Twisted 的“神奇”部分。我无法以一般方式扩展wait_for_events,因为它的实现完全取决于操作系统如何使所需事件可用。而且,鉴于操作系统是复杂而棘手的野兽,我无法以特定方式对其进行扩展,同时保持其足够简单以回答您的问题。
这个函数的意思是,要求操作系统或它周围的 Python 包装器阻止,直到一个或多个先前向它注册的对象 - 至少,像侦听端口和建立的连接之类的东西,但也可能是诸如可能被点击的按钮之类的东西 - 是“准备工作”。当它们从网络到达时,这项工作可能正在从套接字中读取一些字节。当缓冲区足够清空以执行此操作时,该工作可能正在向网络写入字节。它可能正在接受新连接或处理已关闭的连接。这些可能的事件中的每一个都是反应器可能在您的对象上调用的函数:dataReceived、buildProtocol、resumeProducing 等,如果您阅读完整的 Twisted 教程,您将了解这些。
一旦我们得到假设的“事件”对象列表,每个对象都有一个虚构的“process”方法(由于历史事故,反应堆中方法的确切名称不同),我们然后回去处理时间:
events += timed_events_until(now())
首先,这是假设events 只是抽象Event 类的list,它有一个process 方法,每种特定类型的事件都需要填写。
此时,循环已经“唤醒”,因为wait_for_events 停止了阻塞。但是,根据“休眠”了多长时间,我们不知道我们可能需要执行多少个定时事件。如果没有发生任何事情,我们可能已经睡了完全超时,但是如果有很多连接处于活动状态,我们可能实际上根本没有睡。因此,我们检查当前时间(“now()”),并将每个定时事件添加到我们需要处理的事件列表中,并在当前时间或之前添加desired_time。
最后,
for event in events:
event.process()
这只是意味着 Twisted 会遍历它必须做的事情列表并执行它们。实际上它当然会处理每个事件周围的异常,并且反应器的具体实现通常只是直接调用事件处理程序而不是创建一个类似Event 的对象来记录需要首先完成的工作,但从概念上讲就是发生了什么。例如,这里的event.process 可能意味着调用socket.recv(),然后调用yourProtocol.dataReceived。
我希望这个扩展的解释可以帮助您理解它。如果你想通过工作了解更多关于 Twisted 的信息,我鼓励你join the mailing list,跳到 IRC 频道,#twisted 讨论应用程序或#twisted-dev 工作在 Twisted 本身,两者在Freenode。