不,您不能中断协程,除非协程将控制权交还给事件循环,这意味着它必须位于yield from
调用内部。asyncio
是单线程的,因此time.sleep(10)
在第二个示例中阻塞调用时,无法运行事件循环。这意味着,当您使用设置的超时时间wait_for
到期时,事件循环将无法对其执行操作。在coro
退出之前,事件循环没有机会再次运行,这时为时已晚。
这就是为什么通常应始终避免任何非异步的阻塞调用的原因。每当调用阻塞而不产生事件循环时,程序中的其他任何内容都无法执行,这可能不是您想要的。如果确实需要执行长时间的阻塞操作,则应尝试使用BaseEventLoop.run_in_executor
它在线程或进程池中运行它,这将避免阻塞事件循环:
import asyncio
import time
from concurrent.futures import ProcessPoolExecutor
@asyncio.coroutine
def coro(loop):
ex = ProcessPoolExecutor(2)
yield from loop.run_in_executor(ex, time.sleep, 10) # This can be interrupted.
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait_for(coro(loop), 1))