tornado.stack_context — Exception handling across asynchronous callbacks¶
StackContext
allows applications to maintain threadlocal-like statethat follows execution as it moves to other execution contexts.
The motivating examples are to eliminate the need for explicitasync_callback
wrappers (as in tornado.web.RequestHandler
), and toallow some additional context to be kept for logging.
This is slightly magic, but it’s an extension of the idea that anexception handler is a kind of stack-local state and when that stackis suspended and resumed in a new context that state needs to bepreserved. StackContext
shifts the burden of restoring that statefrom each call site (e.g. wrapping each AsyncHTTPClient
callbackin async_callback
) to the mechanisms that transfer control fromone 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 astack_context-aware library like tornado.ioloop or tornado.iostream(for example, if you’re writing a thread pool), usestack_context.wrap() before any asynchronous operations to capture thestack context from where the operation was started.
- If you’re writing an asynchronous library that has some sharedresources (such as a connection pool), create those shared resourceswithin a with stack_context.NullContext(): block. This will preventStackContexts from leaking from one request to another.
- If you want to write something like an exception handler that willpersist across asynchronous calls, create a new StackContext (orExceptionStackContext), and make your asynchronous calls in a withblock that references your StackContext.
Note that the parameter is a callable that returns a contextmanager, not the context itself. That is, where for anon-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 deactivationcallback. Run this callback when the StackContext is no longerneeded to ensure that it is not propagated any further (note thatdeactivating a context does not affect any instances of thatcontext that are currently pending). This is an advanced featureand not necessary in most applications.
- class
tornado.stackcontext.
ExceptionStackContext
(_exception_handler)[源代码]¶
Specialization of StackContext for exception handling.The supplied
exception_handler
function will be called in theevent of an uncaught exception in this context. The semantics aresimilar to a try/finally clause, and intended use cases are to logan error, close a socket, or similar cleanup actions. Theexc_info
triple(type, value, traceback)
will be passed to theexception_handler function.If the exception handler returns true, the exception will beconsumed and will not be propagated to other exception handlers.
- class
tornado.stack_context.
NullContext
[源代码]¶
Resets theStackContext
.Useful when creating a shared resource on demand (e.g. an
AsyncHTTPClient
) where the stack that caused the creating isnot relevant to future operations.
tornado.stackcontext.
wrap
(_fn)[源代码]¶
Returns a callable object that will restore the currentStackContext
when executed.Use this whenever saving a callback to be executed later in adifferent execution context (either in a different thread orasynchronously in the same thread).
tornado.stackcontext.
run_with_stack_context
(_context, func)[源代码]¶
Run a coroutinefunc
in the givenStackContext
.It is not safe to have a
yield
statement within awith StackContext
block, so it is difficult to use stack context withgen.coroutine
.This helper function runs the function in the correct context whilekeeping theyield
andwith
statements syntactically separate.Example:
3.1 新版功能.
原文:
https://tornado-zh-cn.readthedocs.io/zh_CN/latest/stack_context.html