[Twisted-Python] A pseudo-deferred class that can be canceled

Andrew Bennetts andrew at bemusement.org
Tue Jan 5 02:01:54 EST 2010


Terry Jones wrote:
> I just wrote the below for fun.  It's untested :-)
> 
> It's a class that you initialize with a callable (f), and which gives you
> back a deferred (d) that will fire when f fires. Alternately, you can fire
> d yourself by calling 'callback' or 'errback' on the class instance and
> passing a value.  That value is returned via d.
> 
> The reason this is useful is that normally when you call a function that
> returns a deferred, you can't easily "cancel" the deferred because it is
> made and controlled by the function you called. The callback or errback on

I think the key thing is to remember there are two distinct parts:

  1) an operation (which eventually will have a result or failure)
  2) a result 
  
A Deferred takes care of managing 2.  It's a placeholder for that
result, and it can track callbacks that need to be called when it
arrives, etc.

We currently don't have any formal idioms for 1.  I think this is what
you're trying to address.  After all, it's not the result that times out
or that you might want to cancel, it's the operation that is expected to
generate it.

I don't think it's wise to conflate the two concepts, so I think
CancellableDeferred is a poor name.

In an ideal world perhaps every Deferred would have a .operation
attribute, so maybe “d.operation.cancel()” and even
“d.operation.getProgressReport()” would be possible, but I doubt that
every piece of code that creates a Deferred would want to pay the cost
of that bookkeepping.  But hopefully you see my point that it's a
connected but distinct concept to the very simple, single-purpose
callback managing object that a Deferred is.

[...]
> I post this partly because it seems cute, but more because it seems like
> issue that's probably been solved by many people. Is there a general
> utility in Twisted for doing this? A better way?

It feels like there should be, but so far people have basically been
managing the logic that fires Deferreds ad hoc.  I don't think this is
an ideal state of affairs, but it seems it's Good Enough most of the
time.

If I were to try improve the situation, I'd be trying to make an
Operation object or something like that, I think.  I think you'd want to
make it support cancellation (and timeouts) when the underlying code
supports it (network requests are often easy to cancel — just close the
socket), and I'm not sure what would be best when the underlying code is
not cancellable (deferToThread is in general impossible to cancel, etc).

So currently your class isn't something I'd use, because I don't think
it helps with any of this.

-Andrew.




More information about the Twisted-Python mailing list