Команды LoopingCall AMP

Почему я получаю сообщение об ошибке при попытке реализовать функцию LoopingCall, вызывающую команды AMP?

from twisted.protocols.amp import AMP
from twisted.python.log import startLogging, err
from twisted.internet.task import LoopingCall
from twisted.internet import reactor
from sys import stdout

import commands

startLogging(stdout)


class MyAMP:

    def __init__(self, host, port):
        destination = TCP4ClientEndpoint(reactor, host, port)
        self.protocol = AMP()
        self.d = connectProtocol(destination, self.protocol)

    def say(self):
        return self.protocol.callRemote(commands.Say,
                                   phrase='Hello world')


def loop(myamp):
    myamp.say()


def main(host, port):
    myamp = MyAMP(host, port)
    lc = LoopingCall(loop, myamp=myamp)
    lc.start(4.0)
    reactor.run()

main('127.0.0.1', 12345)

Ошибка при звонке myamp.say() внутри цикла:

2013-08-16 12:28:58-0400 [-] Starting factory <twisted.internet.endpoints.OneShotFactory instance at 0x92273ec>
2013-08-16 12:28:58-0400 [-] Unhandled error in Deferred:
2013-08-16 12:28:58-0400 [-] Unhandled Error
    Traceback (most recent call last):
      File "lib/client.py", line 35, in <module>
        main('127.0.0.1', 12345)
      File "lib/client.py", line 32, in main
        lc.start(4.0)
      File "/usr/local/lib/python2.7/site-packages/twisted/internet/task.py", line 173, in start
        self()
      File "/usr/local/lib/python2.7/site-packages/twisted/internet/task.py", line 218, in __call__
        d = defer.maybeDeferred(self.f, *self.a, **self.kw)
    --- <exception caught here> ---
      File "/usr/local/lib/python2.7/site-packages/twisted/internet/defer.py", line 137, in maybeDeferred
        result = f(*args, **kw)
      File "lib/client.py", line 26, in loop
        myamp.say()
      File "lib/client.py", line 22, in say
        phrase='Hello world')
      File "/usr/local/lib/python2.7/site-packages/twisted/protocols/amp.py", line 821, in callRemote
        return co._doCommand(self)
      File "/usr/local/lib/python2.7/site-packages/twisted/protocols/amp.py", line 1778, in _doCommand
        self.requiresAnswer)
      File "/usr/local/lib/python2.7/site-packages/twisted/protocols/amp.py", line 752, in _sendBoxCommand
        box._sendTo(self.boxSender)
      File "/usr/local/lib/python2.7/site-packages/twisted/protocols/amp.py", line 577, in _sendTo
        proto.sendBox(self)
    exceptions.AttributeError: 'NoneType' object has no attribute 'sendBox'

2013-08-16 12:28:58-0400 [Uninitialized] AMP connection established (HOST:IPv4Address(TCP, '127.0.0.1', 50457) PEER:IPv4Address(TCP, '127.0.0.1', 12345))

2 ответа

Решение

Вы пытаетесь callRemote до того, как соединение установлено. LoopingCall will, by default, immediately run its function when you start it. Вместо того чтобы делать lc.start(4.0), делать lc.start(4.0, now=False), This will wait four second before the first call.

В обычной среде, где сетевое соединение стабильно, способ @habnabit будет работать, но в реальном мире задержка соединения не может быть оценена, как вы ожидаете. Лучшее решение этой проблемы - циклический вызов должен выполняться после того, как клиент amp подключен следующим образом.

from twisted.protocols.amp import AMP
from twisted.python.log import startLogging, err
from twisted.internet.task import LoopingCall
from twisted.internet import reactor, endpoints
from sys import stdout

import commands

startLogging(stdout)


class MyAMP:
    def __init__(self, host, port):
        destination = endpoints.TCP4ClientEndpoint(reactor, host, port)
        self.protocol = AMP()
        self.d = endpoints.connectProtocol(destination, self.protocol)


def loop (proto, ) :
    return proto.callRemote(commands.get_user, key='Hello world')

def main(host, port):
    def _cb_connected (proto, ) :
        lc = LoopingCall(loop, proto, )
        lc.start(4.0)
        return

    myamp = MyAMP(host, port)
    myamp.d.addCallback(_cb_connected, )
    reactor.run()

    return

main('127.0.0.1', 12345, )
Другие вопросы по тегам