我正在通过异步文档中的以下代码。
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操作,因此写方法还应该等待吗?
但是,我现在能够理解为什么可以等待reader.read而不是writer.write了?由于它们都是I / O操作,因此写方法还应该等待吗?
不必要。read()和之间的基本不对称性write()是read()必须返回实际数据,而write()纯粹是出于副作用。因此read() 必须等待,因为当数据尚不可用时,它需要暂停调用协程。另一方面,write()可以(通过异步方式)通过将数据存储在某个缓冲区中并安排将其写入适当的时间来实现。
read()
write()
这种设计具有重要的后果,例如,写入数据的速度快于另一面的读取速度,这会导致缓冲区无限制地膨胀,并且write()有效地丢失了期间的异常。这两个问题都通过调用来解决,该调用writer.drain()施加了反压,即将缓冲区写出到OS,必要时将协程挂起。这样做直到缓冲区大小降至阈值以下。该write()文档建议“调用后write()应加drain()。”。
缺乏背压write()是由于在基于回调的层之上实现了异步流的结果,在该层中,非异步write()比完全异步的替代方案更方便使用。请参阅本文章由纳撒尼尔Ĵ史密斯,笔者三人,该主题的详细处理。