I'm trying to implement a function that will act as a Twisted client. It's called from code I don't have control over. I tried something like (this taken from the pbsimpleclient.py example code):
# 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()
And the caller would make a call like:
remcall(hello=1, world=2)
remcall(hi=3, there=4)
But as you may have guessed, it gives a "twisted.internet.error.ReactorNotRestartable" error.
What's the best way to do this? I'm not so worried about getting a response from the remote end, but I should know if it's failing and why.
The answer is to use crochet.
# 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
Then the caller just calls
remcall(hello=1, world=2)
remcall(hi=3, there=4)
and crochet's @wait_for handles running remcall inside the reactor thread.