asyncio 如何理解非阻塞操作的任务已完成
How asyncio understands that task is complete for non-blocking operations
我正在尝试了解 asyncio 的工作原理。至于 I/O 操作我了解到,当调用 await 时,我们在 EventLoop 中注册 Future 对象,然后调用 epoll 获取属于 Future 对象的套接字,准备好为我们提供数据。在我们 运行 注册回调并恢复函数执行后。
但是,我无法理解的是,如果我们不为 I/O 操作使用 await 会发生什么。 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())
await
不会自动屈服于事件循环,只有当异步函数(等待链中的任何地方)请求暂停时才会发生,通常是由于 IO 或超时未就绪。
在您的示例中,事件循环永远不会返回,您可以通过在 while
循环之前移动“阻塞”打印并将 main
更改为 await asyncio.gather(my_coro(3.0), my_coro(3.0))
来轻松验证这一点。您将观察到协程是按顺序执行的(“阻塞”后跟“完成”,全部重复两次),而不是并行执行(“阻塞”后跟另一个“阻塞”然后两次“完成”)。这样做的原因是根本没有机会进行上下文切换 - my_coro
一次执行就好像它们是一个普通函数一样,因为 none 它的等待曾经选择暂停。
我正在尝试了解 asyncio 的工作原理。至于 I/O 操作我了解到,当调用 await 时,我们在 EventLoop 中注册 Future 对象,然后调用 epoll 获取属于 Future 对象的套接字,准备好为我们提供数据。在我们 运行 注册回调并恢复函数执行后。
但是,我无法理解的是,如果我们不为 I/O 操作使用 await 会发生什么。 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())
await
不会自动屈服于事件循环,只有当异步函数(等待链中的任何地方)请求暂停时才会发生,通常是由于 IO 或超时未就绪。
在您的示例中,事件循环永远不会返回,您可以通过在 while
循环之前移动“阻塞”打印并将 main
更改为 await asyncio.gather(my_coro(3.0), my_coro(3.0))
来轻松验证这一点。您将观察到协程是按顺序执行的(“阻塞”后跟“完成”,全部重复两次),而不是并行执行(“阻塞”后跟另一个“阻塞”然后两次“完成”)。这样做的原因是根本没有机会进行上下文切换 - my_coro
一次执行就好像它们是一个普通函数一样,因为 none 它的等待曾经选择暂停。