我使用asyncio
建立TCP连接:
reader, writer = await asyncio.open_connection(addr)
我需要保持连接活着。为此,我要存储一对(reader, writer)
以供将来通信。但是,我不知道reader
何时有数据要阅读。我该怎么办?当读者准备就绪时,有没有办法制作处理程序?
答案 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.gather
和asyncio.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
方法。)