ficapy
12/2/2013 - 7:09 PM

An example of using a StackContext to store request data globally in Tornado. See https://groups.google.com/d/msg/python-tornado/8izNLhYj

An example of using a StackContext to store request data globally in Tornado.

See https://groups.google.com/d/msg/python-tornado/8izNLhYjyHw/TNKGa9fgvpUJ for motivation and further discussion.

import threading


class ThreadRequestContext(object):
    """A context manager that saves some per-thread state globally.
    Intended for use with Tornado's StackContext.
    
    Provide arbitrary data as kwargs upon creation,
    then use ThreadRequestContext.data to access it.
    """
    
    _state = threading.local()
    _state.data = {}

    class __metaclass__(type):
        # property() doesn't work on classmethods,
        #  see http://stackoverflow.com/q/128573/1231454
        @property
        def data(cls):
            if not hasattr(cls._state, 'data'):
               return {}
            return cls._state.data

    def __init__(self, **data):
        self._data = data

    def __enter__(self):
        self._prev_data = self.__class__.data
        self.__class__._state.data = self._data

    def __exit__(self, *exc):
        self.__class__._state.data = self._prev_data
        del self._prev_data
        return False
import tornado


class RequestContextHandler(tornado.web.RequestHandler):
    
    def _execute(self, transforms, *args, **kwargs):
        # following the example of:
        #  https://github.com/bdarnell/tornado_tracing/blob/master/tornado_tracing/recording.py
        
        global_data = {}  # add whatever here, e.g. self.request

        with tornado.stack_context.StackContext(functools.partial(ThreadRequestContext, **global_data)):
            super(RequestContextHandler, self)._execute(transforms, *args, **kwargs)
            
# elsewhere, use ThreadRequestContext.data => a dict