SaltyCrane Blog — Notes on JavaScript and web development

Can't block for a Deferred in Twisted

Despite the existence of the promising waitForDeferred/deferredGenerator and the newer inlineCallbacks, it appears there is no way to block while waiting for a Deferred. Brian Granger described the problem on the Twisted mailing list:

I have a function that returns a Deferred. I need to have the result of this Deferred returned in a (apparently) blocking/synchronous manner:
def myfuncBlocking():
  d = myfuncReturnsDeferred()
  ...
  result =

  return result
I need to be able to call this function like:
result = myfuncBlocking()
The question is how to get the result out of the Deferred() and make it *look* like myfuncBlocking() has blocked.
glyph provided the succinct answer (as well as an interesting commentary on using Twisted the wrong way).
This issue has been discussed repeatedly - long story short, it's just a bad idea.

Hmmm, maybe learning Twisted will be harder than I thought.

Update 2008-10-20: Marcin Kasperski wrote a good example comparing raw deferreds, deferred generators, and inline callbacks.

Comments


#1 Erik commented on :

You can easily use Queue.Queue to turn a Defrred call into a blocking call:

def block_on(d, timeout=None):
    q = Queue()
    d.addBoth(q.put)
    try:
        ret = q.get(timeout is not None, timeout)
    except Empty:
        raise Timeout
    if isinstance(ret, Failure):
        ret.raiseException()
    else:
        return ret

make sure you never make blocking calls from the reactor thread though.