IronPython-0.6 is now available!

Sam Holden sholden at flexal.cs.usyd.edu.au
Sat Jul 31 00:29:11 EDT 2004


On Sat, 31 Jul 2004 13:37:35 +1000,
	Derek Thomson <derek.thomson at gmail.com> wrote:
> On Fri, 30 Jul 2004 08:50:16 +0200, Valentino Volonghi aka Dialtone
><dialton3#nospam.jjjjkikk at virgilio.it> wrote:
>> On Fri, 30 Jul 2004 10:11:13 +1000, Derek Thomson wrote:
>>
>> Err... What do you mean? Twisted has, at least, 3 different ways of doing
>> RPC: Perspective Broker, SOAP and XML-RPC.
>
> Yeah, I know - I said "easily" :) It's basically the client side API I
> have a problem with:
>
>>
>> ====
>> from twisted.spread import pb
>> from twisted.internet import reactor
>> from twisted.python import util
>>
>> factory = pb.PBClientFactory()
>> reactor.connectTCP("localhost", 8789, factory)
>> d = factory.getRootObject()
>> d.addCallback(lambda object: object.callRemote("echo", "hello network"))
>> d.addCallback(util.println)
>> d.addCallback(lambda _: reactor.stop())
>> reactor.run()
>> ====
>
> So, why can't it just be basically:
>
> object.echo("hello network")
>
> ... as it is in CORBA and (other) XML-RPC and SOAP toolkits I've used.
>
> I also have a problem with the insistence on the use of asynchronous
> callbacks. In order to use the result of the RPC call later in the
> main flow of my code, I have to somehow block in the main thread for
> the the result to be returned from the server via the callback - this
> is something that can be done for me, and is handled simply and
> transparently in other RPC toolkits/mechanisms I've used.

Twisted is asynchronous so obviously it makes such a demand. You don't
have a "main thread" to block anyway - twisted calls your code for
you...

Obviously if you don't like that style of programming you won't like
twisted.

>
> I'll try to characterize this with a simple example. How would I write
> something like this, where I have three distributed objects:
>
> i = an_object.get_value()
> j = another_object.get_value()
> k = yet_another_object.combine(i, j)

So that doesn't call another_object.get_value() until an_object.get_value()
completes?

That's be nasty for high latency (due to network delays or lots of server
computation or whatever) RPC.

>
> ... and now finally use "k" in my code?
>
> I could be missing something, but isn't that going to turn into a mess
> of dependant callbacks in Twisted? Aren't I going to have to write a
> whole lot of code that blocks until the results come back? I don't
> mean this as a challenge or a judgement anything, I'd honestly like to
> know - I would like to look further into Twisted but was pretty much
> put off by this issue right from the start.

I must admit I haven't been using twisted for long, and I haven't used RPC
at all, but my first crack at it would be (based on the original example):

The server:
===
from twisted.spread import pb
from twisted.internet import reactor

class Echoer(pb.Root):
    def remote_echo(self, st):
        print 'echoing:', st
        return st

    def remote_reverse(self, st):
        print 'reversing:', st
        l = list(st)
        l.reverse()
        return ''.join(l)

    def remote_concat(self, a, b):
        print 'concating:', a, 'and', b
        return a+b

if __name__ == '__main__':
    reactor.listenTCP(8789, pb.PBServerFactory(Echoer()))
    reactor.run()
===

The client:
===
from twisted.spread import pb
from twisted.internet import reactor
from twisted.python import util
from twisted.internet import defer

def do_stuff(obj):
        d1 = obj.callRemote("echo", "abc")
        d2 = obj.callRemote("reverse", "abc")
        dl = defer.DeferredList([d1, d2])
        dl.addCallback(lambda r: obj.callRemote("concat", r[0][1], r[1][1]))
        dl.addCallback(util.println)
        dl.addCallback(lambda _: reactor.stop())

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

That's missing error checking and all that stuff, but it seems simple
enough.

Replace util.println with a callback that does the 'and now finally use
"k" in my code' stuff.

I also only used the one remote object, but that's easy to change.




More information about the Python-list mailing list