在下面的asyncio
Python程序中,bar_loop
应该是连续运行的,循环之间有1秒的延迟。
当我们简单地
async def bar_loop(self):
while True:
print('bar')
字符串
但是,当我们添加一个asyncio.sleep(1)
时,循环将结束,而不是循环。
async def bar_loop(self):
while True:
print('bar')
await asyncio.sleep(1)
型
为什么asyncio.sleep()
会导致bar_loop
立即退出?我们怎么能让它以1秒的延迟循环?
完整示例:
import asyncio
from typing import Optional
class Foo:
def __init__(self):
self.bar_loop_task: Optional[asyncio.Task] = None
async def start(self):
self.bar_loop_task = asyncio.create_task(self.bar_loop())
async def stop(self):
if self.bar_loop_task is not None:
self.bar_loop_task.cancel()
async def bar_loop(self):
while True:
print('bar')
await asyncio.sleep(1)
if __name__ == '__main__':
try:
foo = Foo()
asyncio.run(foo.start())
except KeyboardInterrupt:
asyncio.run(foo.stop())
型
在Ubuntu 20.04上使用Python 3.9.5。
2条答案
按热度按时间fsi0uk1n1#
这种行为与调用
asyncio.sleep
无关,而是与创建任务而不做其他任何事情的预期行为有关。任务将在thetcio循环中并行运行,而其他只使用协程和await表达式的代码可以被认为是以线性模式运行的-然而,由于它们是“不碍事的”-让我们称之为“可见的执行路径”,也无法阻止这种流动在这种情况下,你的程序只是到达了
start
方法的末尾,没有任何东西被“等待”,所以start
循环只是完成了它的执行。如果你没有显式的代码可以与
bar_loop
并行运行,那就等待任务的执行。将你的start
方法改为:字符串
fsi0uk1n2#
公认的答案对我来说是不够的,因为它没有解释为什么观察到的行为会发生。
似乎在使用
asyncio.run
时,所有任务都会在主“入口点”协程完成后被取消。所以这段代码:
字符串
印刷品:
型
发生这种情况的原因是
asyncio.run
的实现,它在表面下使用loop.run_until_complete
。看看实现(文件asyncio/base_events.py
):型
所以很明显,当“main”任务完成时,所有其他任务都会被取消,循环也会停止。