1 回答
TA贡献1886条经验 获得超2个赞
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 os
import sys
async 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()协程会将其所有行都写入写入器传输。
添加回答
举报