30

我在 Twisted 中开发反向代理时遇到了麻烦。它有效,但似乎过于复杂和令人费解。很多感觉就像巫毒教一样。

网络上或书中是否有任何简单、可靠的异步程序结构示例?一种最佳实践指南?当我完成我的程序时,我希望仍然能够以某种方式看到结构,而不是看着一碗意大利面。

4

1 回答 1

65

Twisted 包含大量示例。尤其是“Finger 的演变”教程,其中包含对异步程序如何从非常小的内核发展到具有大量移动部件的复杂系统的详尽解释。您可能感兴趣的另一篇文章是关于简单编写服务器的教程。

关于 Twisted 甚至其他异步网络库(例如asyncoreMINAACE )要记住的关键是,您的代码仅在发生某些事情时才会被调用。我最常听到的听起来像“巫毒”的部分是回调的管理:例如,Deferred. 如果您习惯于编写直线运行的代码,并且只调用立即返回结果的函数,那么等待某些东西回叫您的想法可能会令人困惑。但是没有什么神奇的,没有关于回调的“巫毒”。在最低级别,反应器只是坐在那里等待少数事情之一发生:

  1. 数据通过连接到达(它将调用dataReceived协议)
  2. 时间已经过去(它会调用一个用 注册的函数callLater)。
  3. 已接受连接(它将调用使用or函数buildProtocol注册的工厂)。listenXXXconnectXXX
  4. 连接已断开(它将调用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,而是一个操作系统调用,如select()or ,由Python 选择模块之poll()类的模块公开。我说“喜欢” ,因为这是一个在平台之间变化很大的 API,而且几乎每个 GUI 工具包都有自己的版本。Twisted 目前为这个主题的 14 种不同变体提供了一个抽象接口。这种 API 提供的共同点是提供一种方式来表示“这是我正在等待的事件列表。去睡觉直到其中一个发生,然后醒来告诉我它是其中一个。 "select

于 2008-09-17T09:29:45.977 回答