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 tornado.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.contextmanagerdefdie_on_error():try:yieldexceptException:logging.error("exception in asynchronous operation",exc_info=True)sys.exit(1)withStackContext(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 tornado.ioloop or tornado.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 withstack_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.

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 withStackContext()ascb: 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.

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.

It is not safe to have a yield statement within a withStackContext
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.coroutinedefincorrect():withStackContext(ctx):# ERROR: this will raise StackContextInconsistentErroryieldother_coroutine()@gen.coroutinedefcorrect():yieldrun_with_stack_context(StackContext(ctx),other_coroutine)