[Twisted-Python] Why do I get an AlreadyCalledError?
Jean-Paul Calderone
exarkun at divmod.com
Sat Feb 28 20:06:22 MST 2009
On Sat, 28 Feb 2009 14:57:33 +0000, Conrad Winchester <conradwinchester at me.com> wrote:
>Thanks Jean-Paul,
>
>Useful information, but then I am confused -
>
>If I am running in a deferred how do I cause the errback to be called
>instead of the normal (non-error) callback? How do I pass a failure object
>to the error handler? How should I do the self.process.errback(fail)?
>
>All of this has to happen inside of the deferred doesn't it, because it is
>the deferred that is doing the work and where the errors will occur?
If a Deferred is a container, it is a container for callbacks and results,
not for executing code. So I wouldn't think about it in terms of "happening
inside of a Deferred". Instead, consider this definition of a function like
runInteraction (but which doesn't involve databases or threads):
def execute(callable, *args):
d = Deferred()
try:
result = callable(*args)
except:
d.errback()
else:
d.callback(result)
return d
In its handling of Deferreds and results, this is largely what runInteraction
does. Notice how any exception raised by `callable´ will be given to the
Deferred to be passed to any registered errbacks (in an "except" suite,
Deferred.errback with no arguments uses sys.exc_info() to find the current
exception). This is a property of the implementation of `execute´, though,
not a property of Deferred. (However, the code which executes the callbacks
or errbacks attached to a Deferred is similar to this.)
So in your case, if you just raise an exception, the errbacks you add to
the Deferred returned by runInteraction will have it passed to them as a
failure. (Sorry for the somewhat disjointed nature of this response, I
started writing this email hours ago and I just noticed I hadn't finished
it, but wanted to send it before I go to bed).
Jean-Paul
More information about the Twisted-Python
mailing list