Цепочка отложенных обратных вызовов
Я пытаюсь связать отложенные ссылки в клиенте AMP следующим образом:
Клиент:
from twisted.internet.endpoints import TCP4ClientEndpoint, connectProtocol
from twisted.protocols.amp import AMP
import commands
def connect_protocol(host, port):
destination = TCP4ClientEndpoint(reactor, host, port)
d = connectProtocol(destination, AMP())
def connect(protocol):
print 'Connecting to server as Mr Spaceman...'
return protocol.callRemote(commands.Connect,
username='Mr Foo')
def say(protocol):
print 'Saying "Hello world" to the server...'
return protocol.callRemote(commands.Say,
phrase='Hello world')
d.addCallback(connect)
d.addCallback(say)
def main(host, port):
connect_protocol(host, port)
print 'Connected to %s:%d...' % (host, port)
reactor.run()
main('127.0.0.1', 12345)
Сервер:
from twisted.internet.protocol import Factory
from twisted.protocols.amp import AMP
import commands
class CommandProtocol(AMP):
def connect(self, username):
print "Received connect command: %s." % (username)
return {}
commands.Connect.responder(connect)
def say(self, phrase):
print "Received phrase \"%s\"." % phrase
return {}
commands.Say.responder(say)
def main(port):
factory = Factory()
factory.protocol = CommandProtocol
reactor.listenTCP(port, factory)
print 'Started AMP server on port %d...' % port
reactor.run()
main(12345)
Только connect()
увольняется на стороне сервера
1 ответ
Сначала включите ведение журнала:
from sys import stdout
from twisted.python.log import startLogging
startLogging(stdout)
Теперь вы увидите, что происходит в программе.
Во-вторых, по крайней мере, есть последняя ошибка, которая регистрирует необработанные сбои на Deferred
поэтому они будут отображаться детерминистически, а не в зависимости от сборщика мусора:
from twisted.python.log import err
...
d.addCallback(connect)
d.addCallback(say)
d.addErrback(err, "connect_protocol encountered some problem")
Наконец, результат Отложенного изменяется обратными вызовами и прикрепленными к нему ошибками. В этом случае аргумент передается say
является результатом Deferred
вернулся connect
, Это не будет тем же аргументом connect
так что вряд ли вы сможете использовать callRemote
в теме.
Вы можете исправить это разными способами. Один из способов, который включает в себя минимальные изменения кода (но не обязательно лучшее решение), состоит в том, чтобы передать протокол как дополнительное значение в результате connect
Deferred
:
def connect(protocol):
print 'Connecting to server as Mr Spaceman...'
d = protocol.callRemote(commands.Connect, username='Mr Foo')
d.addCallback(lambda result: (protocol, result))
return d
def say((protocol, result)):
print 'Saying "Hello world" to the server...'
return protocol.callRemote(commands.Say,
phrase='Hello world')