Reputation: 1408
I am new to twisted and having trouble with the following script.
When I run the following:
#!/usr/bin/env python
from twisted.internet import defer
from twisted.web.client import getPage, reactor
def success(results):
print 'success'
def error(results):
print 'error'
return results
def finished(results):
print 'finished'
reactor.stop()
tasks = []
d = getPage('thiswontwork').addCallback(success).addErrback(error)
tasks.append(d)
dl = defer.DeferredList(tasks)
dl.addCallback(finished)
reactor.run()
I get the following output:
error
finished
Unhandled error in Deferred:
Unhandled Error
Traceback (most recent call last):
Failure: twisted.internet.error.ConnectionRefusedError: Connection was refused by other side: 61: Connection refused.
My question is why am I getting an unhandled error when I seem to have caught the error with my error callback?
Upvotes: 2
Views: 8307
Reputation: 1832
The problem is that in your error
def you return result
which, given it was called by an error back is a Failure
object, and returning a Failure
object is one of the two criteria for re-raising the error state. See the following blurb from krondo's twisted intro - part 9:
Now, in synchronous code we can “re-raise” an exception using the raise keyword without any arguments. Doing so raises the original exception we were handling and allows us to take some action on an error without completely handling it. It turns out we can do the same thing in an errback. A deferred will consider a callback/errback to have failed if:
- The callback/errback raises any kind of exception, or
- The callback/errback returns a Failure object.
Since an errback’s first argument is always a Failure, an errback can “re-raise” the exception by returning its first argument, after performing whatever action it wants to take.
Yup, just tried it, if you change:
def error(results):
print 'error'
return results
to
def error(results):
print 'error'
return
You won't re-raise the error state, so it won't percolate back to the reactor, and won't cause the traceback thats annoying you.
P.S. I can't recommend krondo's twisted introduction enough! It may be really long but if you can get through it, you really will be able to produce code in twisted and these sort of behaviors won't be a mystery.
P.P.S I see you have previous SO question (Python DeferredList callback reporting success when deferreds raise error) about deferred's that might be the reason you built the code this way. I think you may have a fundamental misunderstanding about the return-value/callback-value of def's involved in deferreds (particularly errbacks). Check out part 9 (though you might have to backup part 7 or even earlier to track it) of krondo's, it really should help clear things up.
Upvotes: 4