[Twisted-Python] Why do I get an AlreadyCalledError?

Jean-Paul Calderone exarkun at divmod.com
Sat Feb 28 22:06:22 EST 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()
            result = callable(*args)
        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).


More information about the Twisted-Python mailing list