Tornado上下文管理器在gen.coroutine中调用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tornado上下文管理器在gen.coroutine中调用相关的知识,希望对你有一定的参考价值。

我现在正在使用AMQP pika库。我想要开发的是上下文管理器或装饰器,它确保连接建立到Rabbit。在装饰器内部使用生成器是不可能的,因为它们必须返回被调用的函数。以下示例引发异常:

def ensure_conn(func):

    @gen.coroutine
    def wrapper(self, *args, **kwargs):
        yield self.connection.ensure_connection()
        return func(*args, **kwargs)

    return wrapper

上下文管理器几乎存在同样的问题。不可能两次使用产量。以下示例引发了生成器未停止的异常。

@contextlib.contextmanager
@gen.coroutine
def ensure_conn(self):
    yield self.ensure_connection()
    yield

请推荐另一种方法?当然,我已经对简单的协程调用感到满意。谢谢。

答案

实际上,有两种方法可以创建上下文管理器,从而确保您可以使用某些内容。就我而言,它与AMQP有关。第一种方法是覆盖concurrent.futures.Future result()方法,强制它返回由contextlib.contextmanager修饰的生成器函数。 ajdavis在他漂亮的图书馆TORO中使用了这种方法。你可以通过导航到this line来看到它。

但是,如果您不想覆盖concurrent.futures.Future对象,那么我建议您浏览以下代码段:

@gen.coroutine
def ensure_connection(*args, **kwargs):
    res = yield _make_connection(timeout=kwargs.pop('timeout', 5), *args, **kwargs)
    raise gen.Return(res)

@gen.coroutine
def ensure(*args, **kwargs):
    res = yield ensure_connection(*args, **kwargs)

    @contextlib.contextmanager
    def func(res):
       try:
          yield  # your wrapped code
       finally:
          pass

    return func(res)

@gen.coroutine
def simple_usage(conn):
    with (yield conn.ensure()) as res:
        # Do your target staff here

conn = ...
IOLoop.add_callback(callback=lambda : simple_usage(conn))

以上是关于Tornado上下文管理器在gen.coroutine中调用的主要内容,如果未能解决你的问题,请参考以下文章

如何配置客户端协议(SQL Server 配置管理器)

上下文管理

使用 Web 套接字的 Tornado 单元测试 - 堆栈上下文呢?

flask 上下文管理 &源码剖析

深入tornado中的协程

深入tornado中的协程