[Twisted-Python] inlineCallbacks + raise exception behavior is different than deferred.errback

Croepha croepha at gmail.com
Thu Apr 3 10:36:09 MDT 2014


Hello:

Please refer to the following script:

import sys
import twisted.internet.defer
import twisted.internet.reactor
import twisted.python.log

print "Twisted version", twisted.version
print "Python version", sys.version

class ExceptionToRaise(Exception):
pass

exception_to_raise = ExceptionToRaise()

@twisted.internet.defer.inlineCallbacks
def icb_error_maker():
"""
Raises an exception implemented as an inline inlineCallbacks
"""
raise exception_to_raise

def pod_error_maker():
"""
Raises an exception implemented as a plain old deferred
"""
deferred = twisted.internet.defer.Deferred()
deferred.errback(exception_to_raise)
return deferred

#ERROR_MAKER_TO_USE = icb_error_maker
ERROR_MAKER_TO_USE = pod_error_maker

@twisted.internet.defer.inlineCallbacks
def intermediate_function3():
 print 'intermediate_function3 1'
try:
 yield ERROR_MAKER_TO_USE()
 except BaseException as exception:
print 'intermediate_function3 exception', repr(exception)
raise
 print 'intermediate_function3 2'


@twisted.internet.defer.inlineCallbacks
def intermediate_function2():
 print 'intermediate_function2 1'
try:
 yield intermediate_function3()
 except BaseException as exception:
print 'intermediate_function2 exception', repr(exception)
raise
 print 'intermediate_function2 2'


@twisted.internet.defer.inlineCallbacks
def intermediate_function1():
 print 'intermediate_function1 1'
try:
 yield intermediate_function2()
 except BaseException as exception:
print 'intermediate_function1 exception', repr(exception)
raise
 print 'intermediate_function1 2'

def run():
d = intermediate_function1()
d.addErrback(twisted.python.log.err)
d.addBoth(lambda n: twisted.internet.reactor.stop())
twisted.internet.reactor.callWhenRunning(run)
twisted.internet.reactor.run()


When ERROR_MAKER_TO_USE = icb_error_maker The output is as follows:

Twisted version [twisted, version 13.2.0]
Python version 2.7.3 (default, Feb 27 2014, 20:00:17)
[GCC 4.6.3]
intermediate_function1 1
intermediate_function2 1
intermediate_function3 1
intermediate_function3 exception ExceptionToRaise()
intermediate_function2 exception ExceptionToRaise()
intermediate_function1 exception ExceptionToRaise()
Unhandled Error
Traceback (most recent call last):
  File
"/home/daveb/bzr_repo/player_rm2/test2/local/lib/python2.7/site-packages/twisted/internet/defer.py",
line 1237, in unwindGenerator
    return _inlineCallbacks(None, gen, Deferred())
  File
"/home/daveb/bzr_repo/player_rm2/test2/local/lib/python2.7/site-packages/twisted/internet/defer.py",
line 1099, in _inlineCallbacks
    result = g.send(result)
  File "icb_error_test1.py", line 52, in intermediate_function2
    yield intermediate_function3()
  File
"/home/daveb/bzr_repo/player_rm2/test2/local/lib/python2.7/site-packages/twisted/internet/defer.py",
line 1237, in unwindGenerator
    return _inlineCallbacks(None, gen, Deferred())
--- <exception caught here> ---
  File
"/home/daveb/bzr_repo/player_rm2/test2/local/lib/python2.7/site-packages/twisted/internet/defer.py",
line 1099, in _inlineCallbacks
    result = g.send(result)
  File "icb_error_test1.py", line 37, in intermediate_function3
    yield ERROR_MAKER_TO_USE()
  File
"/home/daveb/bzr_repo/player_rm2/test2/local/lib/python2.7/site-packages/twisted/internet/defer.py",
line 1228, in unwindGenerator
    gen = f(*args, **kwargs)
  File "icb_error_test1.py", line 19, in icb_error_maker
    raise exception_to_raise
__main__.ExceptionToRaise:

However when ERROR_MAKER_TO_USE = pod_error_maker The output is as follows:

Twisted version [twisted, version 13.2.0]
Python version 2.7.3 (default, Feb 27 2014, 20:00:17)
[GCC 4.6.3]
intermediate_function1 1
intermediate_function2 1
intermediate_function3 1
intermediate_function3 exception ExceptionToRaise()
intermediate_function2 exception ExceptionToRaise()
intermediate_function1 exception ExceptionToRaise()
Unhandled Error
Traceback (most recent call last):
Failure: __main__.ExceptionToRaise:

Questions:

1. Why is it that icb_error_maker raises an exception that retains its
traceback while pod_error_maker does not?
2. How might one retain the inlineCallback trace when handling
Exceptions/Failures from deferreds? (I would prefer a universal method, ie
not doing a Try/Reraise at every yield point) ?
3. I have taken a look at the code in twisted/internet/defer.py and I am
not sure where the distinction between inlineCallback exceptions and
deferred errors are being made.  Would someone please elaborate on this
process.

Thanks
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://twistedmatrix.com/pipermail/twisted-python/attachments/20140403/3bc10f7b/attachment-0001.html>


More information about the Twisted-Python mailing list