<div style="font-family:Calibri,sans-serif">Hi,</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">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:</div>
<div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">$ cat inlinecallbacks-loses-exception-types.py</div><div style="font-family:Calibri,sans-serif">#!/usr/bin/env python</div><div style="font-family:Calibri,sans-serif">
 </div><div style="font-family:Calibri,sans-serif">import sys, traceback</div><div style="font-family:Calibri,sans-serif">from twisted.internet         import defer, reactor</div><div style="font-family:Calibri,sans-serif">
 </div><div style="font-family:Calibri,sans-serif">class MyException(Exception):</div><div style="font-family:Calibri,sans-serif">  pass</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">
def go2():</div><div style="font-family:Calibri,sans-serif">    &quot;An ordinary deferred-returning function that will return a deferred which is ready to errback()&quot;</div><div style="font-family:Calibri,sans-serif">
    try:</div><div style="font-family:Calibri,sans-serif">        raise MyException(&#39;xyz&#39;)</div><div style="font-family:Calibri,sans-serif">    except Exception as e:</div><div style="font-family:Calibri,sans-serif">
        return defer.fail() # errs back with current exception context</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">    return defer.succeed(1) # unreachable code</div>
<div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">@defer.inlineCallbacks</div><div style="font-family:Calibri,sans-serif">def go_inlinecb():</div><div style="font-family:Calibri,sans-serif">
    try:</div><div style="font-family:Calibri,sans-serif">        x = yield go2()</div><div style="font-family:Calibri,sans-serif">        print &#39;no exception raised&#39;</div><div style="font-family:Calibri,sans-serif">
    except MyException as e:</div><div style="font-family:Calibri,sans-serif">        print &#39;got my custom exception&#39;</div><div style="font-family:Calibri,sans-serif">        traceback.print_exc()</div><div style="font-family:Calibri,sans-serif">
    except Exception as e:</div><div style="font-family:Calibri,sans-serif">        print &#39;got a garden variety exception&#39;</div><div style="font-family:Calibri,sans-serif">        traceback.print_exc()</div><div style="font-family:Calibri,sans-serif">
 </div><div style="font-family:Calibri,sans-serif">def go_noinlinecb():</div><div style="font-family:Calibri,sans-serif">    d = go2()</div><div style="font-family:Calibri,sans-serif">    def cb(data):</div><div style="font-family:Calibri,sans-serif">
        print &#39;got data in cb: %s&#39; % (data)</div><div style="font-family:Calibri,sans-serif">    def eb(failure):</div><div style="font-family:Calibri,sans-serif">        try:</div><div style="font-family:Calibri,sans-serif">
            failure.raiseException()</div><div style="font-family:Calibri,sans-serif">        except MyException as e:</div><div style="font-family:Calibri,sans-serif">            print &#39;got my custom exception&#39;</div>
<div style="font-family:Calibri,sans-serif">            traceback.print_exc()</div><div style="font-family:Calibri,sans-serif">        except Exception as e:</div><div style="font-family:Calibri,sans-serif">            print &#39;got a garden variety exception&#39;</div>
<div style="font-family:Calibri,sans-serif">            traceback.print_exc()</div><div style="font-family:Calibri,sans-serif">    d.addCallbacks(cb, eb)</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">
if sys.argv[1] == &#39;inline&#39;:</div><div style="font-family:Calibri,sans-serif">    reactor.callWhenRunning(go_inlinecb)</div><div style="font-family:Calibri,sans-serif">elif sys.argv[1] == &#39;noinline&#39;:</div><div style="font-family:Calibri,sans-serif">
    reactor.callWhenRunning(go_noinlinecb)</div><div style="font-family:Calibri,sans-serif">reactor.callLater(2, reactor.stop)</div><div style="font-family:Calibri,sans-serif">reactor.run()</div><div style="font-family:Calibri,sans-serif">
 </div><div style="font-family:Calibri,sans-serif">$ ./inlinecallbacks-loses-exception-types.py inline </div><div style="font-family:Calibri,sans-serif">got a garden variety exception</div><div style="font-family:Calibri,sans-serif">
Traceback (most recent call last):</div><div style="font-family:Calibri,sans-serif">  File &quot;./inlinecallbacks-loses-exception-types.py&quot;, line 21, in go_inlinecb</div><div style="font-family:Calibri,sans-serif">    x = yield go2()</div>
<div style="font-family:Calibri,sans-serif">Exception: xyz</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">$ ./inlinecallbacks-loses-exception-types.py noinline</div><div style="font-family:Calibri,sans-serif">
got my custom exception</div><div style="font-family:Calibri,sans-serif">Traceback (most recent call last):</div><div style="font-family:Calibri,sans-serif">  File &quot;./inlinecallbacks-loses-exception-types.py&quot;, line 36, in eb</div>
<div style="font-family:Calibri,sans-serif">    failure.raiseException()</div><div style="font-family:Calibri,sans-serif">  File &quot;/sw/external/twisted-py27-11.0.0/lib/python/twisted/python/failure.py&quot;, line 338, in raiseException</div>
<div style="font-family:Calibri,sans-serif">    raise self.type, self.value, self.tb</div><div style="font-family:Calibri,sans-serif">MyException: xyz</div><div style="font-family:Calibri,sans-serif"> </div><div style="font-family:Calibri,sans-serif">
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?</div>
<div><br></div><div>Thanks,<br clear="all"><div><br></div>-- <br>Benjamin Rutt<br>
<br>
</div>