Python异步io流

时间:2018-10-02 17:39:19

标签: python-3.x sockets tcp async-await python-asyncio

我正在查看异步文档中的以下代码。

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操作,因此写方法还应该等待吗?

1 个答案:

答案 0 :(得分:3)

  

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

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

此设计具有重要的后果,例如,写入数据的速度快于另一面的读取速度,这会导致缓冲区无限制地膨胀,并且write()期间的异常会被有效地丢失。这两个问题都可以通过调用writer.drain()来解决,该threshold应用 backpressure ,即将缓冲区写出到OS,必要时将协程挂起。直到缓冲区大小降到article以下为止。 write()文档建议“对write()的呼叫后应跟write()。”

drain()中缺乏背压是由于在基于回调的层之上实现了异步流,其中非异步write()比完全异步使用起来更加方便替代。请参见Nathaniel J Smith的作者trio的{{3}},以获取对该主题的详细处理。