2

現在、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 を 2 回使用することはできません。次の例では、ジェネレーターが停止しないという例外が発生します。

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

別のアプローチをお勧めしますか? もちろん、単純なコルーチンの呼び出しにはすでに満足しています。ありがとうございました。

4

1 に答える 1

3

実際、コンテキスト マネージャを作成する方法は 2 つあります。私の場合はAMQPへの接続でした。最初の方法は、メソッドをオーバーライドconcurrent.futures.Future result()して、 で装飾されたジェネレーター関数を返すように強制することcontextlib.contextmanagerです。ajdavisは、彼の優れたライブラリTOROでこのアプローチを使用しました。この行に移動すると表示されます。

ただし、オブジェクトをオーバーライドしたくない場合は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))
于 2013-09-20T06:13:05.750 に答える