我现在正在使用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
上下文管理器几乎存在相同的问题。不可能两次使用yield。下面的示例引发异常,即生成器未停止。
@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))
关于python - Tornado 上下文管理器在gen.coroutine中调用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18866607/