如何知道 StreamReader 何时准备就绪?

How to know when StreamReader is ready?

我正在使用 asyncio 建立 TCP 连接:

reader, writer = await asyncio.open_connection(addr)

我需要保持联系。为此,我存储了一对 (reader, writer) 用于将来的通信。但是,不知道什么时候reader有数据可以读取。我能用它做什么?当 reader 准备好时,有没有办法制作处理程序?

However, I don't know when reader has data to read. What can I do with it?

知道 reader 流何时有数据要读取的明显方法是 await 它:

data = await reader.read(1024)

这将立即 return 数据,或者 暂停 当前协程,允许其他协程取得进展,并且仅在 reader 有一些数据要读取。您可以编写一个 执行 通信的协程,并存储驱动它的 task ,而不是存储 reader/writer 以供将来通信使用:

async def communicate():
    reader, writer = await asyncio.open_connection(addr)
    # an echo server
    while True:
        line = await reader.readline()
        if not line:
            break
        writer.write(line)
        await writer.drain()  # backpressure, see https://tinyurl.com./hqylfay

task = loop.create_task(communicate())
# the task can itself be awaited, canceled, etc.

asyncio 背后的想法 stream API is to write such sequential-looking code, leaving it to asyncio to handle polling of file descriptors and scheduling of tasks. You can use combinators like asyncio.gather and asyncio.wait 到 运行 数千个并行的此类轻量级协程。

Is there a way to make a handler, when the reader is ready?

如果您需要基于回调的 API,您应该使用较低级别的 transports and protocols instead. However, if you are already working with streams, but still occasionally need an ordinary callback, you can get it by obtaining a Future:

future = asyncio.ensure_future(reader.read(1024))
future.add_done_callback(your_callback)

Future 具有相当于协程处理程序的作用。 Once read would no longer block, the done-callback will be invoked by the event loop with a single argument, the future. The future will have finished, and its result() 方法可用于检索接收到的数据或异常。

(以上内容适用于 asyncio 中的任何协程或未来兼容对象,而不仅仅是 StreamReader 方法。)