Understanding Twisted Deferred Objects in Python
This article explains how Twisted's Deferred objects manage asynchronous callbacks and errbacks in Python, demonstrating their usage with code examples, error handling, and integration with the reactor for real‑world asynchronous operations.
Deferred objects in the Twisted framework are used to handle callbacks, which is crucial for Twisted's asynchronous model.
Each Deferred consists of paired callback and errback chains; initially both are empty. Callbacks are added in pairs, and when a result is produced the Deferred fires the chains in the order they were added.
Example using addCallback :
<code>from twisted.internet.defer import Deferred
def myCallback(result):
print result
d = Deferred()
d.addCallback(myCallback)
d.callback("Triggering callback.")
</code>Running this prints “Triggering callback.”, showing how a Deferred is created, a success callback registered, and then triggered.
Similarly, addErrback registers an error handler:
<code>from twisted.internet.defer import Deferred
def myErrback(failure):
print failure
d = Deferred()
d.addErrback(myErrback)
d.errback(ValueError("Triggering errback."))
</code>The error is wrapped in a Failure object and printed.
Twisted ensures that callbacks and errbacks are always paired; when using addCallback or addErrback a pass‑through is added for the opposite side to keep the chain length equal. Both can be added together with addCallbacks :
<code>d = Deferred()
d.addCallbacks(myCallback, myErrback)
d.callback("Triggering callback.")
</code>A more realistic example integrates the reactor and demonstrates how a Deferred can be returned from an asynchronous operation, converting a headline to HTML or raising an error if it is too long:
<code>from twisted.internet import reactor, defer
class HeadlineRetriever(object):
def processHeadline(self, headline):
if len(headline) > 50:
self.d.errback(Exception("The headline ``%s'' is too long!" % (headline,)))
else:
self.d.callback(headline)
def _toHTML(self, result):
return "<h1>%s</h1>" % (result,)
def getHeadline(self, input):
self.d = defer.Deferred()
reactor.callLater(1, self.processHeadline, input)
self.d.addCallback(self._toHTML)
return self.d
def printData(result):
print result
reactor.stop()
def printError(failure):
print failure
reactor.stop()
h = HeadlineRetriever()
d = h.getHeadline("Breaking News: Twisted Takes us to the Moon!")
d.addCallbacks(printData, printError)
reactor.run()
</code>If the headline is under 50 characters the program prints the HTML heading; if it exceeds the limit the error is printed as a Failure.
Key points: a Deferred can be fired only once, callbacks pass their result to the next callback, errbacks receive exceptions or Failure objects, and unhandled errors propagate as unhandled failures.
Python Programming Learning Circle
A global community of Chinese Python developers offering technical articles, columns, original video tutorials, and problem sets. Topics include web full‑stack development, web scraping, data analysis, natural language processing, image processing, machine learning, automated testing, DevOps automation, and big data.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.