# `tornado.stack_context` — Exception handling across asynchronous callbacks

`StackContext` allows applications to maintain threadlocal-like state that follows execution as it moves to other execution contexts.

The motivating examples are to eliminate the need for explicit `async_callback` wrappers (as in `tornado4.web.RequestHandler`), and to allow some additional context to be kept for logging.

This is slightly magic, but it’s an extension of the idea that an exception handler is a kind of stack-local state and when that stack is suspended and resumed in a new context that state needs to be preserved. `StackContext` shifts the burden of restoring that state from each call site (e.g. wrapping each `AsyncHTTPClient` callback in `async_callback`) to the mechanisms that transfer control from one context to another (e.g. `AsyncHTTPClient` itself, `IOLoop`, thread pools, etc).

Example usage:

    @contextlib.contextmanager
    def die_on_error():
        try:
            yield
        except Exception:
            logging.error("exception in asynchronous operation",exc_info=True)
            sys.exit(1)

    with StackContext(die_on_error):
        # Any exception thrown here *or in callback and its descendants*
        # will cause the process to exit instead of spinning endlessly
        # in the ioloop.
        http_client.fetch(url, callback)
    ioloop.start()

Most applications shouldn’t have to work with `StackContext` directly. Here are a few rules of thumb for when it’s necessary:

- If you’re writing an asynchronous library that doesn’t rely on a stack_context-aware library like `tornado4.ioloop` or `tornado4.iostream` (for example, if you’re writing a thread pool), use `stack_context.wrap()` before any asynchronous operations to capture the stack context from where the operation was started.
- If you’re writing an asynchronous library that has some shared resources (such as a connection pool), create those shared resources within a `with stack_context.NullContext():` block. This will prevent `StackContexts` from leaking from one request to another.
- If you want to write something like an exception handler that will persist across asynchronous calls, create a new `StackContext` (or `ExceptionStackContext`), and make your asynchronous calls in a `with` block that references your `StackContext`.

exception `tornado.stack_context.``StackContextInconsistentError`

class `tornado.stack_context.``StackContext`(context_factory)

  Establishes the given context as a StackContext that will be transferred.

  Note that the parameter is a callable that returns a context manager, not the context itself. That is, where for a non-transferable context manager you would say:

      with my_context():

  StackContext takes the function itself rather than its result:

      with StackContext(my_context):

  The result of `with StackContext() as cb:` is a deactivation callback. Run this callback when the StackContext is no longer needed to ensure that it is not propagated any further (note that deactivating a context does not affect any instances of that context that are currently pending). This is an advanced feature and not necessary in most applications.

class `tornado.stack_context.``ExceptionStackContext`(exception_handler)

  Specialization of StackContext for exception handling.

  The supplied `exception_handler` function will be called in the event of an uncaught exception in this context. The semantics are similar to a try/finally clause, and intended use cases are to log an error, close a socket, or similar cleanup actions. The `exc_info` triple `(type, value, traceback)` will be passed to the exception_handler function.

  If the exception handler returns true, the exception will be consumed and will not be propagated to other exception handlers.

class `tornado.stack_context.``NullContext`

  Resets the `StackContext`.

  Useful when creating a shared resource on demand (e.g. an `AsyncHTTPClient`) where the stack that caused the creating is not relevant to future operations.

`tornado.stack_context.``wrap`(fn)

  Returns a callable object that will restore the current `StackContext` when executed.

  Use this whenever saving a callback to be executed later in a different execution context (either in a different thread or asynchronously in the same thread).

`tornado.stack_context.``run_with_stack_context`(context, func)

  Run a coroutine `func` in the given `StackContext`.

  It is not safe to have a `yield` statement within a `with StackContext` block, so it is difficult to use stack context with `gen.coroutine`. This helper function runs the function in the correct context while keeping the `yield` and `with` statements syntactically separate.

  Example:

      @gen.coroutine
      def incorrect():
          with StackContext(ctx):
              # ERROR: this will raise StackContextInconsistentError
              yield other_coroutine()

      @gen.coroutine
      def correct():
          yield run_with_stack_context(StackContext(ctx), other_coroutine)

  New in version 3.1.