试图用一个事件停止循环,但它没有

据我所知,asyncio这应该只打印 0 到 4,但它会显示完整的 10 位数字。


stop_loop协程不应该在我点击 5 后停止等待事件并取消循环吗?


import asyncio


async def run():

    for i in range(10):

        if i == 5:

            e.set()

        print(i)


async def stop_loop():

    await e.wait()

    l.stop()


e = asyncio.Event()


l = asyncio.get_event_loop()

l.set_debug(True)


l.create_task(stop_loop())

l.create_task(run())


try:

    l.run_forever()

finally:

    l.close()

输出是


machine:programs user$ python3 conditional_stop.py 

0

1

2

3

4

5

6

7

8

9


慕村9548890
浏览 162回答 1
1回答

MM们

asyncio通过在作为协程实现的任务之间切换来工作。一个协同程序是一个合作的程序,在协程自愿放弃控制权曾经在一段时间,以让该asyncio事件循环切换到另一个任务。这与线程不同,在线程中每个任务可以并且将被调度程序“随意”中断。并且协程每次await在另一个协程上使用时都会放弃控制,通常是在涉及某些 I/O 的地方。I/O 很慢,asyncio事件循环负责监控 I/O 流的变化,以便它可以知道哪些任务准备好再次做更多的工作。你的问题是你有一个不合作的协程:async def run():    for i in range(10):        if i == 5:            e.set()        print(i)该例程没有await语句,因此它永远不会放弃对事件循环的控制。不能运行其他协程。你可以等待一个asyncio.sleep()电话:async def run():    for i in range(10):        if i == 5:            e.set()        print(i)        await asyncio.sleep(0.01)  # wait 1/100th of a second另一种选择是将print(i)调用(这是一个 I/O 操作)替换为使用非阻塞输出流的调用。如果您不在 Windows 上,则可StreamWriter以为以下对象创建异步 I/O 包装器sys.stdout:import osimport sysasync def run():    # create an async writer for sys.stdout    loop = asyncio.get_event_loop()    writer_transport, writer_protocol = await loop.connect_write_pipe(        asyncio.streams.FlowControlMixin, os.fdopen(sys.stdout.fileno(), 'wb'))    writer = asyncio.streams.StreamWriter(        writer_transport, writer_protocol, None, loop)    for i in range(10):        if i == 5:            e.set()        writer.write(b'%d\n' % i)        await writer.drain()不幸的是,尚不支持为 Windows 控制台流创建异步 I/O 流,请参阅Pyton 问题 #26832,您必须改用线程池执行程序。请注意,甚至与后者协同程序,也不能保证该stop协程将实际运行不久后,足以e.set()被称为取消run()它读取前10名!在处理之后,循环可以自由地将控制权交还给同一个协程await writer.drain()。向sys.stdout流缓冲区写入短行很快,唯一要做.drain()的就是让写入协程有时间刷新内部传输缓冲区;sys.stdout大多数情况下直接非阻塞写入成功,这并不总是有足够的空间stop_loop()来跳入,run()协程会将其所有行都写入写入器传输。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python