Python的Twisted Reactor如何工作?

时间:2016-01-31 07:03:33

标签: python twisted event-loop reactor

最近,我一直在深入研究Twisted文档。从我收集的内容来看,Twisted功能的基础是它的事件循环称为“Reactor”。 reactor侦听某些事件并将它们分派给已设计用于处理这些事件的已注册回调函数。在书中,有一些伪代码描述了Reactor的功能,但我无法理解它,它对我没有任何意义。

 while True:
     timeout = time_until_next_timed_event()
     events = wait_for_events(timeout)
     events += timed_events_until(now())
     for event in events:
         event.process()

这是什么意思?

2 个答案:

答案 0 :(得分:29)

如果它不明显,它被称为 reactor ,因为它对...做出反应 事。循环是它如何反应。

一次一行:

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)

这一行是#34;魔法" Twisted的一部分。我无法以一般方式扩展wait_for_events,因为它的实现取决于操作系统如何使所需事件可用。而且,鉴于操作系统是复杂而棘手的野兽,我不能以特定的方式对其进行扩展,同时保持其足够简单以回答您的问题。

这个函数的意思是,要求操作系统或它周围的Python包装器阻塞,直到之前注册的一个或多个对象 - 至少是监听端口和已建立的连接之类的东西,也可能是可能被点击的按钮之类的东西 - "准备工作"。当工作从网络到达时,工作可能是从套接字中读取一些字节。当缓冲区足够清空时,工作可能是将字节写入网络。它可能正在接受新连接或处理已关闭的连接。这些可能的事件中的每一个都是反应堆可能调用对象的函数:dataReceivedbuildProtocolresumeProducing等,如果您完成完整的Twisted教程,您将了解这些函数。

一旦我们获得了我们的假设"事件列表"对象,每个对象都有一个虚构的" process"方法(由于历史事故,反应堆中方法的确切名称不同),我们再回到处理时间:

     events += timed_events_until(now())

首先,假设events只是抽象list类的Event,它具有process方法,每种特定类型的事件都需要填写

此时,循环已经醒来",因为wait_for_events,停止阻止。但是,我们不知道我们可能需要执行多少次定时事件,这些事件基于多长时间才能执行?#34; asleep"对。如果nothign正在进行,我们可能已经睡了整个超时,但如果有很多连接处于活动状态,我们可能根本没有时间睡觉。因此,我们检查当前时间(" now()"),然后我们添加到我们需要处理的事件列表中,每个定时事件都带有desired_time,或者之前,现在。

最后,

     for event in events:
         event.process()

这只是意味着Twisted会查看它必须执行的操作列表并执行它们。实际上它当然会处理每个事件的异常,而反应器的具体实现通常直接调用事件处理程序,而不是创建一个类似Event的对象来记录需要先完成的工作,但是从概念上讲,这就是发生的事情。 event.process此处可能意味着调用socket.recv(),然后调用yourProtocol.dataReceived,例如。

我希望这个扩展的解释可以帮助您了解它。如果您想通过努力了解更多有关Twisted的信息,我建议您join the mailing list,跳转到IRC频道,#twisted来讨论应用或{{{ 1}}在Freenode上处理Twisted本身。

答案 1 :(得分:2)

我将尝试详细说明:

  • 程序产生控制并在等待事件时进入休眠状态。 我想这里最有趣的部分是事件。 活动是: 在外部需求(接收网络数据包,点击键盘,定时器,不同的程序调用)程序接收控制(在一些其他线程或 在特殊例程中)。不知何故, wait_for_events 中的睡眠中断, wait_for_events 返回。

  • 在发生控制时,事件处理程序将该事件的信息存储到某些数据结构 events 中,后者用于执行有关事件的操作(事件 - >过程)。 在进入和退出 wait_for_events 之间的时间内不仅会发生一次,而且会发生很多事件,所有事件都必须进行处理。 event->进程()过程是自定义的,通常应调用有趣的部分 - 用户的扭曲代码。