【问题标题】:How to know when StreamReader is ready?如何知道 StreamReader 何时准备就绪?
【发布时间】:2018-05-08 15:51:54
【问题描述】:

我正在使用asyncio 进行 TCP 连接:

reader, writer = await asyncio.open_connection(addr)

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

【问题讨论】:

    标签: python networking network-programming python-asyncio


    【解决方案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 的作用相当于协程处理程序。一旦read 不再阻塞,事件循环将使用单个参数future 调用完成回调。未来就结束了,它的result()方法可以用来取回接收到的数据或者异常。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-31
      • 2023-03-11
      • 2019-09-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 2018-03-11
      • 1970-01-01
      相关资源
      最近更新 更多