我正在试图理解协程,我知道它们使用的是单线程,而await
关键字的意思是“把控制权交还给其他正在运行的协程,并给它们一个运行的机会”。
我举下面的例子:
import asyncio
import time
async def long_function():
# it takes almost 1 sec to execute it
for _ in range(50000000):
pass
async def count():
for x in range(10):
print(x)
#await asyncio.sleep(0)
await long_function()
async def gather():
await asyncio.gather(count(), count())
asyncio.run(gather())
字符串
我希望这段代码异步运行,并给予如下输出:
0
0
1
1
2
2
...
型
然而,它提供了:
0
1
2
3
...
0
1
2
3
...
型
当我取消asyncio.sleep(0)
的注解时,输出与预期的一样-异步。
有谁能解释一下为什么使用await long_function()
不足以将控制传递给其他协程吗?它是如何在一些较低的级别上工作的,以帮助我理解。
谢谢
2条答案
按热度按时间jgwigjjp1#
当你取消注解await.sleep(0)时,它会引入一个小的暂停,允许事件循环切换到其他协程。这是因为await.sleep(0)是一种非阻塞的方式,可以将控制权交给事件循环,允许其他任务运行。通过偶尔放弃控制权来使长时间运行的CPU绑定任务合作是一个常见的技巧。
以下是发生的事情的分解:
1.'count'协程运行并打印0。
1.当long_function运行时,其他协程(比如另一个计数协程)正在等待轮到它们,但是它们直到long_function完成才能得到它。
一般来说,如果你正在处理CPU绑定的任务,并希望实现并行性,你可能会考虑使用“concurrent.futures”或其他多处理技术。
31moq8wy2#
在阅读这篇有用的文章后:https://bbc.github.io/cloudfit-public-docs/asyncio/asyncio-part-1https://bbc.github.io/cloudfit-public-docs/asyncio/asyncio-part-2
我发现我误解了
await
关键字的含义,因为这个关键字的行为取决于我们正在等待的对象。有三种类型的awaitable:所以我的代码没有异步运行的原因是我等待了一个协程,所以它被添加到堆栈并执行。
使用
await asyncio.sleep(0)
是将控制权交还给asyncio.sleep
,因为asyncio.sleep
在下面使用Future。我的原始代码可以重写为异步的,像这样:
字符串