как перестать читать, не ожидая сообщения - PullRequest
0 голосов
/ 13 ноября 2018

в приведенном ниже коде мы асинхронно ожидаем получения данных. Но как перестать ждать чтения, когда больше не ждут данных. Причина, по которой я спрашиваю об этом, заключается в том, что я хочу реализовать класс, который продолжает прослушивать поступающие сообщения в отдельном потоке, используя asyncio.run_coroutine_threadsafe, и хочет прервать прослушивание, как только мой тест закончится (чтобы освободить соединение с сокетом).

import asyncio

@asyncio.coroutine
def tcp_echo_client(message, loop):
    reader, writer = yield from asyncio.open_connection('127.0.0.1', 8888,
                                                    loop=loop)

    print('Send: %r' % message)
    writer.write(message.encode())

    data = yield from reader.read(100)
    print('Received: %r' % data.decode())

    print('Close the socket')
    writer.close()

message = 'Hello World!'
loop = asyncio.get_event_loop()
loop.run_until_complete(tcp_echo_client(message, loop))
loop.close()

Ответы [ 2 ]

0 голосов
/ 19 ноября 2018

Streamreader не поставляется с таймаутом https://github.com/python/asyncio/issues/96, поэтому, как только вы начнете читать, вы не сможете остановиться.Для меня я отправил закрывающее сообщение и обработал в моем клиенте, что при обнаружении закрывающего сообщения оно не должно идти для дальнейшего чтения.Вот так я и перестал читать.После вызова reader.read он продолжает ждать сообщения (даже после вызова writer.close) и поддерживает подключение сокета до тех пор, пока объект не будет уничтожен.

0 голосов
/ 13 ноября 2018

Чтобы остановить ожидание, отмените задачу , которая запускает сопрограмму. Например:

# tcp_echo_client as in your code

message = 'Hello World!'
loop = asyncio.get_event_loop()
task = loop.create_task(tcp_echo_client(message, loop))
loop.call_later(5, task.cancel)  # cancel the task after five seconds
try:
    loop.run_until_complete(task)
except asyncio.CancelledError:
    pass
loop.close()

Если вы используете asyncio.run_coroutine_threadsafe, обратите внимание, что он возвращает объект concurrent.futures.Future, который сам имеет метод cancel. Отмена будущего, возвращенная run_coroutine_threadsafe, будет замечена asyncio и приведет к отмене задачи в потоке цикла событий.

...