Skip to main content

tornado.stack_context —跨异步回调的异常处理

StackContext 允许应用程序在移动到其他执行上下文时保持执行之后的线程本地状态。

激励示例是消除对显式 async_callback 包装器(如在 tornado.web.RequestHandler 中)的需要,并允许保留一些附加上下文以用于日志记录。

这有点神奇,但它是一个想法的延伸,一个异常处理程序是一种堆栈本地状态,当该堆栈被暂停和恢复在一个新的上下文状态需要保留。 StackContext 将从每个呼叫站点恢复该状态(例如,将 async_callback 中的每个 AsyncHTTPClient 回叫)包括到将控制从一个上下文转移到另一个上下文的机制(例如 AsyncHTTPClient 本身,IOLoop,线程池等)的负担。

用法示例:

@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()

大多数应用程序不应直接与 StackContext 一起工作。这里有一些经验规则,当有必要时:

  • 如果您正在编写一个不依赖于stack_context感知库(如 tornado.iolooptornado.iostream)的异步库(例如,如果您正在编写一个线程池),请在任何异步操作之前使用 stack_context.wrap() 捕获堆栈上下文操作开始。

  • 如果您正在编写一个具有一些共享资源(例如连接池)的异步库,请在 with stack_context.NullContext(): 块中创建这些共享资源。这将防止 StackContexts 从一个请求泄漏到另一个请求。

  • 如果你想编写一个异常处理程序,它将在异步调用中持久化,创建一个新的 StackContext (或 ExceptionStackContext),并在引用你的 StackContextwith 块中进行异步调用。

class tornado.stack_context.StackContext(context_factory)[源代码]

建立给定的上下文作为将被传输的StackContext。

请注意,该参数是一个可返回上下文管理器的可调用,而不是上下文本身。也就是说,对于一个不可转移的上下文管理器,你会说:

with my_context():

StackContext接受函数本身而不是其结果:

with StackContext(my_context):

with StackContext() as cb: 的结果是去激活回调。当不再需要StackContext时,运行此回调,以确保不再进一步传播(注意,停用上下文不会影响当前正在等待的上下文的任何实例)。这是一个高级功能,在大多数应用程序中不是必需的。

class tornado.stack_context.ExceptionStackContext(exception_handler)[源代码]

专门用于StackContext的异常处理。

在这种情况下,如果发生未捕获异常,将调用提供的 exception_handler 函数。语义与try/finally子句类似,预期的用例是记录错误,关闭套接字或类似的清除操作。 exc_info 三元组 (type, value, traceback) 将被传递给exception_handler函数。

如果异常处理程序返回true,则异常将被消耗,并且不会传播到其他异常处理程序。

class tornado.stack_context.NullContext[源代码]

重置 StackContext

在创建按需共享资源(例如 AsyncHTTPClient)时很有用,其中导致创建的堆栈与未来操作不相关。

tornado.stack_context.wrap(fn)[源代码]

返回一个可调用对象,在执行时将恢复当前 StackContext

每当保存一个回调以在以后在不同的执行上下文中(在不同的线程中或在同一线程中异步地执行)时使用。

tornado.stack_context.run_with_stack_context(context, func)[源代码]

在给定的 StackContext 中运行协同 func

with StackContext 块中具有 yield 语句是不安全的,因此很难与 gen.coroutine 一起使用堆栈上下文。此辅助函数在正确的上下文中运行函数,同时保持 yieldwith 语句在语法上分离。

例:

@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)

3.1 新版功能.