views:

43

answers:

1

Can we use deferred (http://twistedmatrix.com/documents/current/core/howto/defer.html) to make an infinite call loop in which a function adds itself to a deferred chain? I tried to do this, but it doesn't work:

d = deferred.Deferred()
first = True

def loopPrinting(dump):
  ch = chr(random.randint(97, 122))
  print ch
  global d, first
  d.addCallback(loopPrinting)
  if first:
    d.callback('a')
    first = False
  return d

loopPrinting('a')

reactor.run()
+2  A: 

This isn't a good use for Deferreds. Instead, try using reactor.callLater:

from twisted.internet import reactor

def loopPrinting():
    print chr(random.randint(97, 122))
    reactor.callLater(1.0, loopPrinting)

loopPrinting()
reactor.run()

Or twisted.internet.task.LoopingCall:

from twisted.internet import task, reactor

def loopPrinting():
    print chr(random.randint(97, 122))

loop = task.LoopingCall(loopPrinting)
loop.start(1.0)
reactor.run()

Your Deferred-based version has a couple problems. First, it defines a callback on a Deferred that returns the same Deferred. Returning a Deferred (let's call it a) from a callback on another Deferred (let's call it b) does something called "chaining". It makes b pause its callback chain until a has a result. In the case where a and b are actually the same Deferred instance, this makes little or no sense.

Second, when adding a callback to a Deferred that already has a result, the callback will be called immediately. In your case, your callback adds another callback. And that callback adds another callback. So you have an infinite loop all contained inside your d.addCallback(loopPrinting) line. This will prevent the reactor from ever running, breaking any other part of your program.

Jean-Paul Calderone
I was trying to avoid callLater in my code, or other method that time-based. I'm trying to make a chain of functions in which one will be executed after the previous is done, so the running of the chain will be independent from time. Does there exist a way to do that ?
Thien
for f in [f1, f2, f3]): f()
Jean-Paul Calderone