Похоже, что вы преодолели первое препятствие - выяснить, как заставить А и В взаимодействовать на всех . Это хорошо, поскольку для большинства людей это самая большая концептуальная задача. Что касается того, чтобы сделать его элегантным , если вы придерживаетесь подхода, который изолирует ваш код протокола от кода приложения, управляющего им (т. Е. «Бизнес-логика»), есть несколько вариантов. Я приведу пример, основанный на отсрочке.
Давайте рассмотрим двух клиентов 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 и установки нового соединения для получения сообщения отделена от фактической реализации протокола (которая полностью в Twisted). Отложенные, возвращаемые почти всеми API-интерфейсами, используемыми здесь, позволяют подключать события так, как того требует ваше приложение.