7

run_until_completeだから私は私のaccept_connection方法になるイベントループを持っています

@asyncio.coroutine
def accept_connection(self):
    assert self.server_socket is not None

    while True:
        client, addr = yield from self.loop.sock_accept(self.server_socket)
        asyncio.async(self.handle_connection(client, addr))

私のhandle_connection方法は次のようになります

 def handle_connection(self, client, addr):
     #removed error checking

    while True:
        try:
            yield from asyncio.wait([con.handle_read_from_connection()], timeout=5.0)
        except (AssertionError, PacketException):
            print("Invalid packet detected!")

最後に私のhandle_read_from_connection(現在)は次のようになります。

@asyncio.coroutine
def handle_read_from_connection(self):
    raise PacketException("hello")

したがって、このメソッドは常にエラーを発生させ、try catch ステートメントの except ブロックにヒットし、検出された無効なパケットを出力する必要があります。代わりに、トレースバックが発生します。

future: Task(<handle_read_from_connection>)<exception=PacketException('hello',)>
Traceback (most recent call last):
  File "/usr/lib/python3.4/asyncio/tasks.py", line 283, in _step
    result = next(coro)
  File "/some_path.py", line 29, in handle_read_from_connection
    raise PacketException("hello")
GameProtocol.GameProtocol.PacketException: hello

ここで何が起こっているのか誰か知っていますか?try catch が機能しないのはなぜですか? これらのエラーをキャッチできるようにするにはどうすればよいですか

4

1 に答える 1

10

からの戻り値を使用する必要がありますasyncio.wait()

import asyncio

class Error(Exception):
    pass

@asyncio.coroutine
def main():
    try:
        done, pending = yield from asyncio.wait([raise_exception()], timeout=1)
        assert not pending
        future, = done # unpack a set of length one
        print(future.result()) # raise an exception or use future.exception()
    except Error:
        print('got exception', flush=True)
    else:
        print('no exception', flush=True)

@asyncio.coroutine
def raise_exception(): # normally it is a generator (yield from)
                       #  or it returns a Future
    raise Error("message")

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()

出力

got exception

の現在の実装でasyncio.coroutineは、関数がジェネレーターでない場合 (あなたの場合のように)、Future を返すため、ジェネレーターに変換する必要があるraise_exception()ため、ジェネレーター オブジェクトを作成するだけなので、呼び出しは例外を発生させません (コルーチン)。

次に、それasyncio.wait()を生成し、同等の処理future.set_exception(exception)が実行されます。

表示されるエラー出力を回避するには; future.result()呼び出すか、future.exception()直接例外を消費する必要があります。

于 2014-05-04T16:09:04.917 に答える