问题描述
据我了解,asyncio.gather
旨在同时运行其参数,并且当协程执行await表达式时,它为事件循环提供了安排其他任务的机会。考虑到这一点,我很惊讶地看到以下代码片段忽略了asyncio.gather
的输入之一。
import asyncio
async def aprint(s):
print(s)
async def forever(s):
while True:
await aprint(s)
async def main():
await asyncio.gather(forever('a'),forever('b'))
asyncio.run(main())
据我了解,发生了以下事情:
- asyncio.run(main())对事件循环进行必要的全局初始化,并计划main()进行执行。
- main()调度asyncio.gather(...)以便执行并等待其结果
- asyncio.gather计划执行forever('a')和forever('b')
- 无论哪个首先执行,它们都会立即等待aprint()并为调度程序提供运行另一个协程的机会(例如,如果我们以“ a”开头,那么我们就有机会开始尝试评估“ b”) ,应该已经安排了执行时间。
- 在输出中,我们将看到一行包含'a'或'b'的行,并且调度程序应该足够公平,以便在足够长的时间内我们至少看到其中每一行。 li>
实际上,这不是我观察到的。相反,整个程序等效于while True: print('a')
。我发现非常有趣的是,即使对代码进行很小的更改也似乎重新引入了公平性。例如,如果我们改用下面的代码,则输出中的“ a”和“ b”大致相等。
async def forever(s):
while True:
await aprint(s)
await asyncio.sleep(1.)
验证似乎似乎与我们花了多长时间或从无穷循环中支出无关,我发现以下更改也提供了公平性。
async def forever(s):
while True:
await aprint(s)
await asyncio.sleep(0.)
有人知道为什么会发生这种不公平以及如何避免这种不公平吗?我想如果有疑问,我可以在任何地方主动添加一个空的sleep语句,并希望该语句就足够了,但是对于我而言,原始代码为何不能按预期运行,这对我来说实在是很明显。
如果这很重要,因为asyncio似乎已经进行了许多API更改,那么我将在Ubuntu盒子上使用Python 3.8.4的原始安装。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)