扭曲的Python中的异步编程
我在Twisted中开发反向代理时遇到了麻烦。它可以工作,但是似乎过于复杂和令人费解。感觉很多像伏都教。
网络或者书籍中是否有任何简单,可靠的异步程序结构示例?一种最佳实践指南?当我完成程序后,我希望仍然能够以某种方式看到结构,而不是看一碗意大利面。
解决方案
回答
如果我们不想使用双绞线,那我曾经有个很棒的指南。这是它的链接。
回答
Twisted包含大量示例。特别是"手指的进化"教程,其中包含对异步程序如何从很小的内核发展为具有许多活动部件的复杂系统的详尽解释。我们可能感兴趣的另一个是有关简单编写服务器的教程。
关于Twisted甚至其他异步网络库(例如asyncore,MINA或者ACE),要记住的关键是,只有在发生某些情况时才调用代码。我最常听到的部分听起来像是" voodoo",是回调的管理:例如," Deferred"。如果我们习惯于编写直线运行的代码,并且只调用会立即返回结果的函数,那么等待某些东西回调想法可能会令人困惑。但是,没有什么神奇的东西,也没有关于回调的"伏都教"。在最低级别,反应堆只是围坐在一旁,等待着少数事情之一发生:
- 数据到达连接(它将在协议上称为" dataReceived")
- 时间已经过去了(它将调用在
callLater
中注册的函数)。 - 连接已被接受(它将在注册有" listenXXX"或者" connectXXX"功能的工厂上调用" buildProtocol")。
- 连接已被删除(在适当的协议上它将称为" connectionLost")
每个异步程序都首先连接一些此类事件,然后启动反应堆以等待它们发生。当然,发生的事件会导致更多事件被挂断或者断开连接,因此程序将继续进行下去。除此之外,有趣或者特别的异步程序结构也没有什么特别的。事件处理程序和回调只是对象,并且代码以通常的方式运行。
这是一个简单的"事件驱动引擎",向我们显示了此过程的简单程度。
# Engine import time class SimplestReactor(object): def __init__(self): self.events = [] self.stopped = False def do(self, something): self.events.append(something) def run(self): while not self.stopped: time.sleep(0.1) if self.events: thisTurn = self.events.pop(0) thisTurn() def stop(self): self.stopped = True reactor = SimplestReactor() # Application def thing1(): print 'Doing thing 1' reactor.do(thing2) reactor.do(thing3) def thing2(): print 'Doing thing 2' def thing3(): print 'Doing thing 3: and stopping' reactor.stop() reactor.do(thing1) print 'Running' reactor.run() print 'Done!'
在像Twisted这样的库的核心处,主循环中的功能不是" sleep",而是诸如Python select模块之类的模块公开的操作系统调用" select()"或者" poll()"。我说"喜欢"select
,是因为这是一个API,在不同平台之间差异很大,并且几乎每个GUI工具包都有其自己的版本。 Twisted当前提供了针对该主题的14种不同变体的抽象界面。此类API提供的常见功能是提供一种说法:"这是我正在等待的事件列表。进入睡眠状态直到其中一个发生,然后醒来并告诉我是哪个。 "