[Twisted-Python] follow up: at what point does reactor.run() need to be called?

Damon Fasching damon.fasching at sbcglobal.net
Wed Apr 7 04:04:34 EDT 2004


Hi,

I'm still confused.

Here is the working code, again.

# ================= server.py ====================
from twisted.spread import pb
from twisted.internet import reactor

class ServerClass(pb.Root):
    def remote_shutdown(self):
        print "server stopping"
        reactor.stop()

reactor.listenTCP(8789,
pb.PBServerFactory(ServerClass()))
reactor.run()

# =========== client.py =============
from twisted.spread import pb
from twisted.internet import reactor

def gotRootObject(obj):
    d = obj.callRemote("shutdown")
    d.addCallback(serverStopped)
    d.addErrback(remoteCallFailure)

def serverStopped(result):
    print 'server stopped'
    stop()

def remoteCallFailure(reason):
    print "remote call failed: %s" % (reason.value)
    stop()

def stop():
    print "client stopping"
    reactor.stop()

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8789, factory)
d = factory.getRootObject()
d.addCallback(gotRootObject)
d.addErrback(remoteCallFailure, "getRootObject")
reactor.run()

============

And here is a modification to the last lines of
client.py which breaks it, in this case causes it to
hang.  (server does not get the shutdown call and
client is not stopped, so it seems the callback for
getRootObject is not executed.)

factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8789, factory)
d = factory.getRootObject()
reactor.run()
d.addCallback(gotRootObject)
d.addErrback(remoteCallFailure, "getRootObject")

==============================================

> It doesn't hang, it just gets the root object, but 
> has no callback to pass it to.

Huh?  What about the line
d.addCallback(gotRootObject)?  It's still there, just
a little further down, and d is still d, the deferred
object returned by getRootObject.  Does the call to
reactor.run() change the deferred, d?

What I really see as a limitation is that it seems
that I must connect to all of my servers before
starting the reactor, something which is only done
once per process.  And because of that, I can't
interact with any of the servers until I have
connected to all of them (because the reactor isn't
running before then).

For example, why does the client hang if I change the
last lines to the following?

reactor.run()
factory = pb.PBClientFactory()
reactor.connectTCP("localhost", 8789, factory)
d = factory.getRootObject()
d.addCallback(gotRootObject)
d.addErrback(remoteCallFailure, "getRootObject")

This seems to be an inevitable sequence of calls if I
want to be able to connect to a server after having
already connected to and intereacted with other
servers.  Start the reactor, do some stuff, and then
at a later point, connect to another server.  If I
substitute those lines for the original last 6 lines,
start the server and start the client...nothing
happens.  They both just sit there.

What have I misunderstood?

How can I connect to a server on the fly?

> The value, that getRootObject() returns is a
Deferred
> object. This is a "delayed" function call (which is
> also non-blocking), so the *real* rootObject is
> passed to the Deferred.callback function.

Right, it's the obj argument of the gotRootObject()
method in the original code.

> -- 
> mp

Thanks,
  Damon





More information about the Twisted-Python mailing list