Error output for bad deferred method signatures?
I'm curious why errors aren't reported when deferreds are fired if the deferred method has a bad signature. For example, if the following is run: import httplib, sys from twisted.web import client from twisted.internet import reactor, threads, defer from twisted.protocols import http from twisted.python import failure class getYahoo(object): def __init__(self): factory = client.HTTPClientFactory("http://www.yahoo.com") reactor.connectTCP("www.yahoo.com",80,factory) factory.deferred.addCallback(self._gotResponse, factory) factory.deferred.addErrback(self._errSendReq, factory) self.deferred = factory.deferred def _gotResponse(self, resp, factory): print "yeah!" print resp def _errSendReq(self, err, factory): print "shucks!" print err def sendRequest(): return getYahoo().deferred if __name__ == '__main__': def test(msg): print msg print respOrErr d = sendRequest() d.addCallback(test, "success") d.addErrback(test, "failure") reactor.run() The deferred _gotResponse() and _errSendReq() fire perfectly, but the test() function in __main__ is not called for "success" or "failure". This is expected as the signature is wrong -- it should be 'test(respOrErr, msg)'. What isn't clear [to me] is why this doesn't produce an error upon firing the deferred, but instead produces an error when the reactor shuts down [via ctrl-c], which could be hours later. I have an instance of this that is more severe, where the error output is *never* produced (maybe because of threading?). Is this the expected behavior, or am I doing something atrocious to produce it? Thanks, Lenny __________________________________ Yahoo! Music Unlimited Access over 1 million songs. Try it free. http://music.yahoo.com/unlimited/
Lenny G Arbage wrote:
'test(respOrErr, msg)'. What isn't clear [to me] is why this doesn't produce an error upon firing the deferred, but instead produces an error when the reactor shuts down [via ctrl-c], which could be hours later.
It does. But as the error happens inside your Deferred chain, it will sit there waiting for an errback to be added, which would handle it. At shutdown you see debug output telling you forgot to handle errors in your Deferred chain. Add d.addErrback(log.err) after all the other deferred handling and errors in the deferred chain will cause log output and will not get complained about.
Perfect. This works as described, and your explanation makes perfect sense. I'm wondering though, if there is a way to do this globally without specifying another errBack for every deferred I call (which, right now numbers about 60 in my little app)? This would be useful for debugging only, of course -- but that's where I'd like to save the several hours trying to figure out why my callbacks weren't firing for the next time I forget to check that all err/callbacks have the correct signatures. Thanks again, Lenny --- Tommi Virtanen <tv@twistedmatrix.com> wrote:
Lenny G Arbage wrote:
'test(respOrErr, msg)'. What isn't clear [to me] is why this doesn't produce an error upon firing the deferred, but instead produces an error when the reactor shuts down [via ctrl-c], which could be hours later.
It does. But as the error happens inside your Deferred chain, it will sit there waiting for an errback to be added, which would handle it. At shutdown you see debug output telling you forgot to handle errors in your Deferred chain.
Add d.addErrback(log.err) after all the other deferred handling and errors in the deferred chain will cause log output and will not get complained about.
_______________________________________________ Twisted-web mailing list Twisted-web@twistedmatrix.com
http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web
__________________________________ Yahoo! Music Unlimited Access over 1 million songs. Try it free. http://music.yahoo.com/unlimited/
Lenny G Arbage wrote:
I'm wondering though, if there is a way to do this globally without specifying another errBack for every deferred I call (which, right now numbers about 60 in my little app)? This would be useful for debugging only, of course -- but that's where I'd like to save the several hours trying to figure out why my callbacks weren't firing for the next time I forget to check that all err/callbacks have the correct signatures.
There already is a global debug output if nothing handled the error (last errback run should return e.g. None). The traceback is dumped to the log. But it is only run when the Deferred is garbace collected, so if something that has infinite lifetime holds a reference to it, it won't be triggered until shutdown. There's no way to do this globally earlier, because you don't know whether a new errback will be added later..
participants (2)
-
Lenny G Arbage
-
Tommi Virtanen