Python асинхронный поток - PullRequest
0 голосов
/ 02 октября 2018

Я просматривал следующий код в asyncio doc.

import asyncio

async def tcp_echo_client(message):
  reader, writer = await asyncio.open_connection(
    '127.0.0.1', 8888)

  print(f'Send: {message!r}')
  writer.write(message.encode())

  data = await reader.read(100)
  print(f'Received: {data.decode()!r}')

  print('Close the connection')
  writer.close()
  await writer.wait_closed()

asyncio.run(tcp_echo_client('Hello World!'))

Однако теперь я могу понять, почему reader.read является ожидаемым, а writer.write - нет?Поскольку они обе являются операциями ввода / вывода, метод записи также должен быть приемлемым, верно?

1 Ответ

0 голосов
/ 03 октября 2018

Однако теперь я могу понять, почему reader.read является ожидаемым, а writer.write - нет?Поскольку они обе являются операциями ввода-вывода, метод записи также должен быть приемлемым, верно?

Не обязательно.Фундаментальная асимметрия между read() и write() заключается в том, что read() должен возвращать фактические данные, тогда как write() действует исключительно из-за побочного эффекта.Так что read() должен быть ожидаемым, потому что он должен приостановить вызывающую сопрограмму, когда данные еще не доступны.С другой стороны, write() может быть (и в асинхронном режиме) реализован путем сохранения данных в некотором буфере и планирования их записи в подходящее время.

У этого плана есть важные последствия, такие какзапись данных быстрее, чем читает другая сторона, вызывает переполнение буфера без границ, а исключения во время write() фактически теряются.Обе проблемы устраняются путем вызова writer.drain(), который применяет противодавление , т.е. записывает буфер в ОС, при необходимости приостанавливая сопрограмму в процессе.Это делается до тех пор, пока размер буфера не опустится ниже порога .В документации write() указано, что «после вызовов write() следует drain()».

Отсутствие противодавления в write() является результатом реализации асинхронных потоков поверх callback-основанный слой, в котором не асинхронный write() гораздо удобнее использовать, чем полностью асинхронная альтернатива.См. статью Натаниэля Дж. Смита , автора trio , для подробного рассмотрения темы.

...