Цепочка отложенных обратных вызовов

Я пытаюсь связать отложенные ссылки в клиенте 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 в теме.

Вы можете исправить это разными способами. Один из способов, который включает в себя минимальные изменения кода (но не обязательно лучшее решение), состоит в том, чтобы передать протокол как дополнительное значение в результате connectDeferred:

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')
Другие вопросы по тегам