但是,我不知道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.gather 和 asyncio.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 方法。)