python - Releasing references to deferred: what's the point -


this pattern mentioned in twisted tutorial standard way avoid firing same deferred twice:

class a(clientfactory): ... def finished(self, result):   if self.deferred not none:     d, self.deferred = self.deferred, none     d.callback(result) 

but understand, deferred won't let (i.e., raise exception if do) call same instance twice. why recreate safety mechanism repeating code everywhere?

as say, second call deferred.callback raise alreadycallederror. idiomatic write code doesn't trigger exception, though. deferred-using code i've written or read tries reserve alreadycallederror indicate programming errors rather normal runtime conditions can safely ignored.

so:

def finished(self, result):     try:         self.deferred.callback(result)     except alreadycallederror:         pass 

is not preferred spelling. think because there might other reasons alreadycallederror raised don't stem finished being called more 1 , kind of error handling obscure cases, potentially hiding bugs.

a second reason throw away deferred instance unexpected exception logging. when deferred garbage collected , has unhandled failure result, failure logged. indicates programming error. deferred can't garbage collected long there references it, though, throwing away reference in factory @ least ensures factory won't keep deferred alive (though application code using deferred still could).

an alternate approach write this:

def finished(self, result):     if self.deferred not none:         self.deferred.callback(result)         self.deferred = none 

this still throws away deferred without tuple unpacking. however, there's problem here.

consider more complete version of a:

class a(clientfactory):     def waituntilfinished(self):         self.deferred = deferred()         return self.deferred      def finished(self, result):         if self.deferred not none:             d, self.deferred = self.deferred, none             d.callback(result) 

as can see, not safe call a.waituntilfinished 2 times before finished has happened once. is, if write:

a = a() x = a.waituntilfinished() y = a.waituntilfinished() 

then can pretty x never receive result. perhaps sad, reasonably document limitation on of api.

now, consider different usage pattern:

a = a() x = a.waituntilfinished()  def dosomething(result):     return a.waituntilfinished() x.addcallback(dosomething) 

this code no longer calls waituntilfinished twice before finished called once. waits until finished called before calling waituntilfinished second time. if documented api being safe call once until resulting deferred fires, might think usage reasonable.

with simpler implementation:

def finished(self, result):     if self.deferred not none:         self.deferred.callback(result)         self.deferred = none 

there's problem. dosomething called result of self.deferred.callback(result). more specifically, dosomething called before self.deferred.callback returns (put way, dosomething called synchronously statement). dosomething calls waituntilfinished creates new deferred , assigns factory's deferred attribute. self.deferred.callback(result) finishes , self.deferred = noneruns - , newdeferred` thrown away, never called.

by setting self.deferred none before invoking callback chain, case avoided.


Comments

Popular posts from this blog

java - Plugin org.apache.maven.plugins:maven-install-plugin:2.4 or one of its dependencies could not be resolved -

Round ImageView Android -

How can I utilize Yahoo Weather API in android -