[Twisted-Python] LoopingCall question
Hello, I am trying to run three deferred LoopingCall chains in parallel. Here is my code below. I am trying to figure out what is the correct way of exiting the polling after I meet some condition that the polling satisfies. Right now I am throwing an exception which is being caught by an errback. I wait for all three deferred chains to complete via a DeferredList with (defer.gatherResults) and then I add a callback to that in order to stop the reactor. class PollingException(twisted.python.failure.Failure): def __init__(self, var): self.var = var def poll(*args): print "poll", args raise PollingException(args[1]) def errorHandle(failure): print "poll exited" return True def stopReactor(result): print "about to stop reactor" reactor.stop() t1 = task.LoopingCall(poll, "A") d1 = t1.start(1, 3) d1.addErrback(errorHandle) t2 = task.LoopingCall(poll, "B") d2 = t2.start(2, 3) d2.addErrback(errorHandle) t3 = task.LoopingCall(poll, "C") d3 = t3.start(3, 3) d3.addErrback(errorHandle) dL = defer.gatherResults([d1, d2, d3]) dL.addCallback(lambda _: reactor.stop()) reactor.run() However, when I run the code and I try to stop the reactor, I get the following exception which I find puzzling. poll ('A',) poll exited poll ('B',) poll exited poll ('C',) poll exited Unhandled error in Deferred: Traceback (most recent call last): File "twisted_poll.py", line 36, in <module> dL.addCallback(lambda _: reactor.stop()) File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 191, in addCallback callbackKeywords=kw) File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 182, in addCallbacks self._runCallbacks() --- <exception caught here> --- File "c:\python25\lib\site-packages\twisted\internet\defer.py", line 317, in _runCallbacks self.result = callback(self.result, *args, **kw) File "twisted_poll.py", line 36, in <lambda> dL.addCallback(lambda _: reactor.stop()) File "c:\python25\lib\site-packages\twisted\internet\base.py", line 342, in stop raise RuntimeError, "can't stop reactor that isn't running" exceptions.RuntimeError: can't stop reactor that isn't running Thanks very much, -Mike
On Wed, 25 Jun 2008 23:29:00 -0400, Mike Preshman <mpresh@gmail.com> wrote:
Hello,
I am trying to run three deferred LoopingCall chains in parallel. Here is my code below. I am trying to figure out what is the correct way of exiting the polling after I meet some condition that the polling satisfies. Right now I am throwing an exception which is being caught by an errback. I wait for all three deferred chains to complete via a DeferredList with (defer.gatherResults) and then I add a callback to that in order to stop the reactor.
class PollingException(twisted.python.failure.Failure):
def __init__(self, var): self.var = var
Don't subclass Failure. Just subclass Exception.
def poll(*args): print "poll", args raise PollingException(args[1])
def errorHandle(failure): print "poll exited" return True
def stopReactor(result): print "about to stop reactor" reactor.stop()
t1 = task.LoopingCall(poll, "A") d1 = t1.start(1, 3) d1.addErrback(errorHandle)
t2 = task.LoopingCall(poll, "B") d2 = t2.start(2, 3) d2.addErrback(errorHandle)
t3 = task.LoopingCall(poll, "C") d3 = t3.start(3, 3) d3.addErrback(errorHandle)
dL = defer.gatherResults([d1, d2, d3]) dL.addCallback(lambda _: reactor.stop())
reactor.run()
However, when I run the code and I try to stop the reactor, I get the following exception which I find puzzling.
[snip] raise RuntimeError, "can't stop reactor that isn't running" exceptions.RuntimeError: can't stop reactor that isn't running
LoopingCall invokes the function it is given immediately, unless you pass now=False to its initializer. This means you're stopping the reactor several times before it's even started. Try making sure the reactor is running before poll is ever called. Jean-Paul
On Wed, 2008-06-25 at 23:29 -0400, Mike Preshman wrote:
Hello,
I am trying to run three deferred LoopingCall chains in parallel. Here is my code below. I am trying to figure out what is the correct way of exiting the polling after I meet some condition that the polling satisfies.
You needn't use LoopingCall, if it's unsuitable - assuming Twisted 8.1: from twisted.internet import defer, reactor, task class _LoopUntil(object): def __init__(self, delay, check): self.delay = delay self.check = check self.result = defer.Deferred() def go(self): task.deferLater(reactor, self.delay, check).addCallbacks( self._gotResult, self._failed) def _gotResult(self, r): if r: d = self.result del self.result self.result.callback(r) else: self.go() def _failed(self, f): self.result.errback(f) del self.result def loopUntil(delay, check): l = _LoopUntil(delay, check) r = l.result l.go() return r
I got it to work with classes. from twisted.internet import utils, reactor, defer, task import twisted import time, sys class Looping: def __init__(self, c, t): self.c = c self.t = t self.count = 0 def myPoll(self, *args): print "poll", args self.count = self.count + 1 if self.count > 3: self.task.stop() def start(self): self.task = task.LoopingCall(self.myPoll, self.c) return self.task.start(self.t) c1 = Looping("A", 1) d1 = c1.start() c2 = Looping("B", 2) d2 = c2.start() c3 = Looping("C", 3) d3 = c3.start() dL = defer.gatherResults([d1, d2, d3]) dL.addCallback(lambda _: reactor.stop()) reactor.run() On Fri, Jun 27, 2008 at 9:44 AM, Itamar Shtull-Trauring <itamar@itamarst.org> wrote:
On Wed, 2008-06-25 at 23:29 -0400, Mike Preshman wrote:
Hello,
I am trying to run three deferred LoopingCall chains in parallel. Here is my code below. I am trying to figure out what is the correct way of exiting the polling after I meet some condition that the polling satisfies.
You needn't use LoopingCall, if it's unsuitable - assuming Twisted 8.1:
from twisted.internet import defer, reactor, task
class _LoopUntil(object):
def __init__(self, delay, check): self.delay = delay self.check = check self.result = defer.Deferred()
def go(self): task.deferLater(reactor, self.delay, check).addCallbacks( self._gotResult, self._failed)
def _gotResult(self, r): if r: d = self.result del self.result self.result.callback(r) else: self.go()
def _failed(self, f): self.result.errback(f) del self.result
def loopUntil(delay, check): l = _LoopUntil(delay, check) r = l.result l.go() return r
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Itamar Shtull-Trauring wrote:
On Wed, 2008-06-25 at 23:29 -0400, Mike Preshman wrote:
Hello,
I am trying to run three deferred LoopingCall chains in parallel. Here is my code below. I am trying to figure out what is the correct way of exiting the polling after I meet some condition that the polling satisfies.
You needn't use LoopingCall, if it's unsuitable - assuming Twisted 8.1:
from twisted.internet import defer, reactor, task
class _LoopUntil(object):
def __init__(self, delay, check): self.delay = delay self.check = check self.result = defer.Deferred()
def go(self): task.deferLater(reactor, self.delay, check).addCallbacks( self._gotResult, self._failed)
def _gotResult(self, r): if r: d = self.result del self.result self.result.callback(r)
What am I missing that stops the above line from raising AttributeError?
else: self.go()
def _failed(self, f): self.result.errback(f) del self.result
def loopUntil(delay, check): l = _LoopUntil(delay, check) r = l.result l.go() return r
regards Steve -- Steve Holden +1 571 484 6266 +1 800 494 3119 Holden Web LLC http://www.holdenweb.com/
Itamar Shtull-Trauring wrote:
def _gotResult(self, r): if r: d = self.result del self.result self.result.callback(r)
What am I missing that stops the above line from raising AttributeError?
That was a typo, thanks for pointing it out. Should be d.callback(). (Deferreds should be derefernced once callbacked or errbacked, since unhandled errors will only get logged on GC.)
participants (4)
-
Itamar Shtull-Trauring -
Jean-Paul Calderone -
Mike Preshman -
Steve Holden