why ExceptionStackContext can't throw exception out of ioloop?

177 views
Skip to first unread message

Jimmy

unread,
Nov 6, 2012, 9:30:12 PM11/6/12
to python-...@googlegroups.com
I'm trying to write a decorator to make async call to be called in an synchronous way (because the async function will be shared by tornado async caller, and script sync caller). But the behavior seems different for exceptions in callback or not in callback. 

Here is my sample code (inspired by bergundy and A. Jesse in this thread: https://groups.google.com/forum/?fromgroups=#!topic/python-tornado/lH_HkmVPUoE )

from tornado import ioloop, gen
from tornado.stack_context import ExceptionStackContext
def sync(fn):
    def wrapper(*args, **kwargs):
        ret = dict(val=None)
        def stop(*args):
            ret['val'] = args
            ioloop.IOLoop.instance().stop()

        def exception_callback(*args, **kwargs):
            print 'in exception callback'
            ioloop.IOLoop.instance().stop()
            print args
            raise args[1]

        with ExceptionStackContext(exception_callback):
            kwargs['callback'] = stop
            fn(*args, **kwargs)
            ioInstance = ioloop.IOLoop.instance()
            ioInstance.start()
        return ret['val']

    return wrapper

class HTTPCaller(object):
    @gen.engine
    def call(self, callback):
        http_client = httpclient.AsyncHTTPClient()
        response = yield gen.Task(http_client.fetch, "https://www.googleaaaa.com/")  ## I made this wrong url in purpose. 
        if response.error:
            print 'rethrow exception'
            response.rethrow()
        else:
            callback(response.body)

if __name__ == "__main__": 
    print 'calling sync test'
    try:
        print 'get sync response = '+str(sync(HTTPCaller().call)())
    except Exception as ex:
        print 'catch exception %s' % (str(ex))
    print 'complete sync test'

I use wrong url to trigger exceptions. If I disconnect network, the exception will be captured in the main function ("nodename nor servname provided, or not known"). If I connect network, the exception is captured by ExceptionStackContext, but not thrown to main function (HTTP 599: Timeout), the return value in main function is None. 

I'm wondering, what makes the difference? How can I throw the exception to the main function for the timeout scenario?

Thank you in advance.
 

Ben Darnell

unread,
Nov 8, 2012, 9:54:08 AM11/8/12
to Tornado Mailing List
After you call IOLoop.stop() you're still in the callback context.  What you want to do is save the exception in exception_callback, and re-raise it outside the IOLoop, i.e. after the 'with ExceptionStackContext' block.  See AsyncTestCase.wait() for an example of this.

-Ben
Reply all
Reply to author
Forward
0 new messages