这听起来像你已经超过了第一个障碍 - 找出如何让A和B互动在所有。这很好,因为对大多数人来说,这是最大的概念挑战。至于如何使优雅,如果您采用的方法可以使您的协议代码与应用程序代码隔离(即“业务逻辑”),则有多种选择。我将举一个基于Deferreds的例子。
让我们考虑两个POP3客户端。您希望第一个检索消息列表,然后第二个从结果列表中检索第一个消息。此示例
from twisted.internet import defer, protocol, reactor
from twisted.mail.pop3 import AdvancedPOP3Client
class MessageDownloader(object):
def __init__(self, host, port, user, password):
self.host = host
self.port = port
self.user = user
self.password = password
self.cc = ClientCreator(reactor, AdvancedPOP3Client)
def connect(self):
"""
Connect to the POP3 server and authenticate. Return a Deferred
which fires with the connected protocol instance.
"""
connDeferred = self.cc.connect(self.host, self.port)
def cbAuthenticate(proto):
loginDeferred = proto.login(user, password)
loginDeferred.addCallback(lambda ignored: proto)
return loginDeferred
connDeferred.addCallback(cbAuthenticate)
return connDeferred
def run(self):
connDeferred = self.connect()
connDeferred.addCallback(self.cbFirstConnection)
return connDeferred
def cbFirstConnection(self, firstProto):
listDeferred = firstProto.listUID()
def cbListed(uidList):
connDeferred = self.connect()
def cbConnected(secondProto):
return secondProto.retrieve(uidList[0])
connDeferred.addCallback(cbConnected)
listDeferred.addCallback(cbListed)
return listDeferred
if __name__ == '__main__':
import sys
MessageDownloader(*sys.argv[1:]).run()
reactor.run()
在这里,所有有关检索的UID的列表,并建立一个新的连接来检索消息的逻辑的是从实际协议实现(这完全是在扭曲的)分开。几乎所有这里使用的API返回的延迟都允许事件被连接起来,但是应用程序需要。