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

时间:2018-05-08 15:51:55

标签: python networking network-programming python-asyncio

我使用asyncio建立TCP连接:

reader, writer = await asyncio.open_connection(addr)

我需要保持连接活着。为此,我要存储一对(reader, writer)以供将来通信。但是,我不知道reader何时有数据要阅读。我该怎么办?当读者准备就绪时,有没有办法制作处理程序?

1 个答案:

答案 0 :(得分:1)

  

但是,我不知道reader何时有数据需要阅读。我该怎么办?

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

data = await reader.read(1024)

这将立即返回数据,或暂停当前协同程序,允许其他协同程序取得进展,并且只有当读取器有一些数据要读取时才恢复此协程。您可以编写一个进行通信的协程,而不是存储读取器/写入器以便将来进行通信,并存储驱动它的task

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背后的想法是编写这样的顺序代码,将其留给asyncio来处理文件描述符的轮询和任务的调度。您可以使用asyncio.gatherasyncio.wait之类的组合来并行运行数千个这样的轻量级协程。

  

当读者准备就绪时,是否有办法制作处理程序?

如果您需要基于回调的API,则应该使用较低级别的transports and protocols。但是,如果您已经在使用流,但仍偶尔需要普通回调,则可以通过获取Future来获取它:

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

Future具有与coroutine处理程序等效的角色。一旦read不再阻塞,事件循环将使用单个参数(未来)调用完成回调。未来将完成,其result()方法可用于检索收到的数据或异常。

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