【问题标题】:How asyncio understands that task is complete for non-blocking operationsasyncio 如何理解非阻塞操作的任务已完成
【发布时间】:2021-03-17 15:57:32
【问题描述】:

我正在尝试了解 asyncio 的工作原理。至于 I/O 操作,我了解到当调用 await 时,我们在 EventLoop 中注册 Future 对象,然后调用 epoll 获取属于 Future 对象的套接字,准备给我们数据。在我们运行注册的回调并恢复函数执行之后。

但是,我无法理解的是,如果我们使用 await 而不是 I/O 操作会发生什么。 eventloop 如何理解该任务已完成?它是为此创建套接字还是使用另一种循环?它使用epoll吗?或者它不添加到Loop并用作生成器?

有一个例子:

import asyncio

async def test():
    return 10



async def my_coro(delay):
    loop = asyncio.get_running_loop()
    end_time = loop.time() + delay
    while True:
        print("Blocking...")
        await test()
        if loop.time() > end_time:
            print("Done.")
            break
async def main():
    await my_coro(3.0)

asyncio.run(main())

【问题讨论】:

    标签: python python-3.x python-asyncio


    【解决方案1】:

    await 不会自动屈服于事件循环,这仅在异步函数(等待链中的任何位置)请求暂停时才会发生,通常是由于 IO 或超时未准备好。

    在您的示例中,事件循环永远不会返回,您可以通过在while 循环之前移动“阻塞”打印并将main 更改为await asyncio.gather(my_coro(3.0), my_coro(3.0)) 来轻松验证。您将观察到协同程序是串行执行的(“阻塞”后跟“完成”,都重复两次),而不是并行执行(“阻塞”后跟另一个“阻塞”,然后两次“完成”)。原因是根本没有机会进行上下文切换 - my_coro 像普通函数一样一次性执行,因为它的等待都没有选择暂停。

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 2019-04-01
      • 1970-01-01
      • 2012-09-15
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多