使用asyncio的程序结构

4

我目前有一个结构如下的程序:

set_up_everthing()

while True:
    if new_client_ready():
        connect_new_client()

    for client in clients:
        if client.is_ready():
            get_input_from(client)

    update_program_state_based_on_input()

    for client in clients:
        if client.is_ready():
            send_output_to(client)

clean_up()

目前,网络I/O使用套接字(sockets)和select函数实现,但我想重写它以使用asyncio库。我认为我已经理解了如何制作简单的asyncio程序。思路似乎是,当你想要进行一些I/O操作时,你需要yield from一个执行该操作的函数。所以,当主循环获得新的客户端时,它会执行yield from accept_client(),当该客户端接收到信息时,它会执行yield from read_information(),以此类推。然而,我无法找出如何将其与程序的其他部分结合起来。

1
这里有一个使用asyncio的简单但完整的端口转发实现:http://pastebin.com/g08YaJyz。 - jfs
2个回答

3
asyncio模块有两个级别的API:低级别的传输和协议API以及高级别的流API。它们就像不同的框架。根据使用的API级别,您的程序结构可能会有很大的差异。
为了避免让自己发疯,通常不要混合使用这两个API级别。
这两个级别的不同之处在于您以不同的方式接收数据。低级别API提供事件驱动的接口,您的程序通过实现回调响应传入的事件 - 框架调用您的代码。高级别API看起来更好,因为它提供了读取器和写入器,您的代码调用框架asyncio文档中的示例应该很容易理解。

谢谢!非常有帮助的答案,表达简单明了。 - Zearin
流和协议风格并没有太大的不同。使用协议的关键是您可能需要在处理传入数据时进行异步请求,因此您必须使用create_task,以便您的数据处理代码可以成为协程。您还需要知道如何在数据就绪时唤醒挂起的任务,例如因为远程对等方回答了请求。 - DanielSank

2

您的代码片段大致描述了asyncio如何工作。

请查看asyncio示例以了解如何使用asyncio:

import asyncio

@asyncio.coroutine
def echo_server():
    yield from asyncio.start_server(handle_connection, 'localhost', 8000)

@asyncio.coroutine
def handle_connection(reader, writer):
    while True:
        data = yield from reader.read(8192)
        if not data:
            break
        writer.write(data)

loop = asyncio.get_event_loop()
loop.run_until_complete(echo_server())
try:
    loop.run_forever()
finally:
    loop.close()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接