[Twisted-Python] inlineCallbacks loses custom exception type?

Benjamin Rutt rutt.4 at osu.edu
Wed Dec 5 22:36:51 EST 2012


Hi,

I am hitting an issue with inlineCallbacks-decorated functions.  It seems
that from within an inlineCallbacks-decorated func, if you yield on another
deferred-returning func, and that deferred-returning func returns a
deferred which will errback with a Failure wrapping a user defined
exception type, then the user defined exception gets repackaged as a common
Exception by the time you are in the inlineCallbacks-decorated function.
It seems to be related to the fact that inside an inlineCallbacks-decorated
func, if you yield on a func, and that func returns a deferred which errs
back, twisted will convert the errback into a synchronous exception that it
raises for you.  That’s all a bit wordy, so maybe some code will help
clarify:

$ cat inlinecallbacks-loses-exception-types.py
#!/usr/bin/env python

import sys, traceback
from twisted.internet         import defer, reactor

class MyException(Exception):
  pass

def go2():
    "An ordinary deferred-returning function that will return a deferred
which is ready to errback()"
    try:
        raise MyException('xyz')
    except Exception as e:
        return defer.fail() # errs back with current exception context

    return defer.succeed(1) # unreachable code

@defer.inlineCallbacks
def go_inlinecb():
    try:
        x = yield go2()
        print 'no exception raised'
    except MyException as e:
        print 'got my custom exception'
        traceback.print_exc()
    except Exception as e:
        print 'got a garden variety exception'
        traceback.print_exc()

def go_noinlinecb():
    d = go2()
    def cb(data):
        print 'got data in cb: %s' % (data)
    def eb(failure):
        try:
            failure.raiseException()
        except MyException as e:
            print 'got my custom exception'
            traceback.print_exc()
        except Exception as e:
            print 'got a garden variety exception'
            traceback.print_exc()
    d.addCallbacks(cb, eb)

if sys.argv[1] == 'inline':
    reactor.callWhenRunning(go_inlinecb)
elif sys.argv[1] == 'noinline':
    reactor.callWhenRunning(go_noinlinecb)
reactor.callLater(2, reactor.stop)
reactor.run()

$ ./inlinecallbacks-loses-exception-types.py inline
got a garden variety exception
Traceback (most recent call last):
  File "./inlinecallbacks-loses-exception-types.py", line 21, in go_inlinecb
    x = yield go2()
Exception: xyz

$ ./inlinecallbacks-loses-exception-types.py noinline
got my custom exception
Traceback (most recent call last):
  File "./inlinecallbacks-loses-exception-types.py", line 36, in eb
    failure.raiseException()
  File
"/sw/external/twisted-py27-11.0.0/lib/python/twisted/python/failure.py",
line 338, in raiseException
    raise self.type, self.value, self.tb
MyException: xyz

So as you can see, it seems that if you use inlineCallbacks, you cannot
‘except MyException’ and catch your own custom exceptions.  Somehow a
generic Exception is constructed.  Is there any workaround or is this a
known issue?

Thanks,

-- 
Benjamin Rutt
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://twistedmatrix.com/pipermail/twisted-python/attachments/20121205/8fa4c263/attachment.htm 


More information about the Twisted-Python mailing list