0

我正在尝试实现一个充当 Twisted 客户端的功能。它是从我无法控制的代码中调用的。我尝试了类似的东西(这取自 pbsimpleclient.py 示例代码):

# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.


from twisted.spread import pb
from twisted.internet import reactor
from twisted.python import util

def remcall(**kw):
    factory = pb.PBClientFactory()
    reactor.connectTCP("localhost", 8789, factory)
    d = factory.getRootObject()
    # kw here is what's passed in via remcall
    d.addCallback(lambda object: object.callRemote("echo", kw))
    d.addCallback(lambda echo: 'server echoed: '+repr(echo))
    d.addErrback(lambda reason: 'error: '+str(reason.value))
    d.addCallback(util.println)
    d.addCallback(lambda _: reactor.stop())
    reactor.run()

来电者会拨打如下电话:

remcall(hello=1, world=2)
remcall(hi=3, there=4)

但正如您可能已经猜到的那样,它给出了“twisted.internet.error.ReactorNotRestartable”错误。

最好的方法是什么?我不太担心从远程端得到响应,但我应该知道它是否失败以及为什么。

4

2 回答 2

2

reactor.run()从函数中删除remcall并将其附加到末尾。同时删除d.addCallback(lambda _: reactor.stop())

def remcall(**kw):
    factory = pb.PBClientFactory()
    reactor.connectTCP("localhost", 8789, factory)
    d = factory.getRootObject()
    # kw here is what's passed in via remcall
    d.addCallback(lambda object: object.callRemote("echo", kw))
    d.addCallback(lambda echo: 'server echoed: '+repr(echo))
    d.addErrback(lambda reason: 'error: '+str(reason.value))
    d.addCallback(util.println)


remcall(hello=1, world=2)
remcall(hi=3, there=3)
reactor.run()    # this should be the last thing to run

反应器只能运行一次。 reactor.stop()函数正在执行,除非您的应用程序需要完全停止运行,否则它不应该执行。这就是你得到ReactorNotRestartable异常的原因。

于 2016-07-02T07:04:18.127 回答
0

答案是使用钩针编织。

# Copyright (c) Twisted Matrix Laboratories.
# See LICENSE for details.

## Add these two lines
from crochet import setup, wait_for
setup()

from twisted.spread import pb
from twisted.internet import reactor
from twisted.python import util

## Add a wait_for decorator
@wait_for(timeout=5.0)
def remcall(**kw):
    factory = pb.PBClientFactory()
    reactor.connectTCP("localhost", 8789, factory)
    d = factory.getRootObject()
    # kw here is what's passed in via remcall
    d.addCallback(lambda object: object.callRemote("echo", kw))
    d.addCallback(lambda echo: 'server echoed: '+repr(echo))
    d.addErrback(lambda reason: 'error: '+str(reason.value))
    d.addCallback(util.println)
## Get rid of the reactor calls, and return d
#    d.addCallback(lambda _: reactor.stop())
#    reactor.run()
    return d

然后调用者只是调用

remcall(hello=1, world=2)
remcall(hi=3, there=4)

和钩针的@wait_for 处理在反应器线程内运行remcall。

于 2016-07-04T12:17:57.993 回答