Skip to main content
 首页 » 编程设计

python之Twisted 中不同的协议(protocol)如何相互交互

2025年05月04日7oomusou

我希望两个不同的协议(protocol)相互交互的场景如下:

A和B是两个不同的协议(protocol)。 首先 A 将与服务器交互并检索一些值。 只有在 A 完成检索值后,B 才会开始与服务器交互。

现在我的问题是,当 A 检索值时,是否有一种优雅的方式来初始化 B。

目前我只是在A的数据处理函数中初始化B。但我不认为这是一种优雅的方式。

我的意思是一种优雅的方式是 B 的初始化由流 Controller 或类似的东西完成,而不是另一个协议(protocol)。

有什么优雅的方法吗?例如使用延迟或任何其他东西。

我刚接触 twisted,对 defered 不是很了解....

非常感谢!

请您参考如下方法:

听起来您已经越过了第一个障碍 - 弄清楚如何让 A 和 B 完全互动。这很好,因为对于大多数人来说,这是最大的概念挑战。至于使其优雅,如果您采用一种方法将协议(protocol)代码与驱动它的应用程序代码(即“业务逻辑”)隔离开来,则有多种选择。我将举一个基于 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 列表和建立新连接以检索消息的逻辑都与实际协议(protocol)实现(完全在 Twisted 中)是分开的。从此处使用的几乎所有 API 返回的 Deferred 允许根据您的应用程序的需要连接事件。