xml-rpc/twisted question

Andrew Bennetts andrew-pythonlist at puzzling.org
Fri Dec 5 23:47:43 CET 2003


On Fri, Dec 05, 2003 at 05:13:07PM +0100, Guyon Morée wrote:
> Hi all,
> 
> Below this message you can see my code. It is a modified version of the
> twisted xml-rpc server examples. I am trying to figure out how to implement
> non-blocking methods. I found out that I have to use 'defer' to do that, but
> I have no clue how to do this. Unfortunately the documentation could not
> make this clear to(unless I am missing some docs). I have already added a
> function called xmlrpc_block to represent a actual 'blocking function'.
> 
> I hope someone can show me how to modify this so the server does not block
> any other clients when xmlrpc_block is called.

You'll have better luck asking this sort of question on the Twisted list, at
twisted-python at twistedmatrix.com... but here goes anyway :)

[...]
>     def xmlrpc_block(self, duration=10):
>         """block the instance for a specified duration"""
>         import time
>         time.sleep(duration)
>         return "i slept %s seconds!" % (str(duration))
> 

Basically, you can't do any blocking operation in the main thread (unless
it's acceptable to block your entire server!).  Either resort to using
threads:

----
from twisted.internet.threads import deferToThread
from twisted.python import log

    def xmlrpc_block(self, duration=10):
        """block the instance for a specified duration"""
        import time
        d = deferToThread(time.sleep, duration)
        d.addCallback(lambda r: "i slept %d seconds!" % duration)
        return d
----

Or even better, don't use a blocking operation in the first place:

----
from twisted.internet.defer import Deferred
from twisted.python import log

    def xmlrpc_block(self, duration=10):
        """block the instance for a specified duration"""
        import time
        d = Deferred()
        reactor.callLater(duration, d.callback, 
                          "i slept %d seconds!" % duration)
        return d
----

The trick with both of these is that Twisted's XML-RPC framework allows you
to return a Deferred instead of a result.  When you return a Deferred,
Twisted won't return anything to the XML-RPC client until the Deferred is
called -- it adds a callback to the Deferred to send the response.  This
gives you the oppurtunity to take as long as you need to answer the request
without blocking the rest of your server.

Note that Deferreds aren't magical.  They are actually very simple objects
that represent a "deferred result", with convenient hooks to add chains of
callbacks (and "errbacks" for error handling) to them.  In Twisted, when an
operation is likely to take a long time, but the function you call to invoke
that operation needs to return immediately, that function will return a
Deferred.  See http://twistedmatrix.com/documents/howto/defer for more
information.

-Andrew.






More information about the Python-list mailing list