小编典典

Python异步io流

python

我正在通过异步文档中的以下代码。

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呢?由于它们都是I / O操作,因此写方法还应该等待吗?


阅读 209

收藏
2021-01-20

共1个答案

小编典典

但是,我现在能够理解为什么可以等待reader.read而不是writer.write了?由于它们都是I / O操作,因此写方法还应该等待吗?

不必要。read()和之间的基本不对称性write()read()必须返回实际数据,而write()纯粹是出于副作用。因此read() 必须等待,因为当数据尚不可用时,它需要暂停调用协程。另一方面,write()可以(通过异步方式)通过将数据存储在某个缓冲区中并安排将其写入适当的时间来实现。

这种设计具有重要的后果,例如,写入数据的速度快于另一面的读取速度,这会导致缓冲区无限制地膨胀,并且write()有效地丢失了期间的异常。这两个问题都通过调用来解决,该调用writer.drain()施加了反压,即将缓冲区写出到OS,必要时将协程挂起。这样做直到缓冲区大小降至阈值以下。该write()文档建议“调用后write()应加drain()。”。

缺乏背压write()是由于在基于回调的层之上实现了异步流的结果,在该层中,非异步write()比完全异步的替代方案更方便使用。请参阅本文章由纳撒尼尔Ĵ史密斯,笔者三人,该主题的详细处理。

2021-01-20