使用asyncio,可以在超时的情况下执行协同路由,以便在超时后将其取消:
@asyncio.coroutine
def coro():
yield from asyncio.sleep(10)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait_for(coro(), 5))
上面的示例按预期工作(5秒后超时)。
然而,当协程不使用asyncio.sleep()
(或其他异步协程)时,它似乎不会超时。示例:
@asyncio.coroutine
def coro():
import time
time.sleep(10)
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.wait_for(coro(), 1))
因为time.sleep(10)
没有被取消,所以这需要10秒以上的时间来运行。在这种情况下,是否可以强制取消联程?
如果应该使用asyncio来解决这个问题,我该怎么做呢?
不,除非将控制权交回事件循环,否则不能中断协程,这意味着它需要在一个
yield from
调用中。asyncio
是单线程的,因此当您在第二个示例中阻塞time.sleep(10)
调用时,事件循环无法运行。这意味着当您使用wait_for
设置的超时过期时,事件循环将无法对其执行操作。直到coro
退出,事件循环才有机会再次运行,此时太晚了。这就是为什么在一般情况下,您应该始终避免任何非异步的阻塞调用;每当调用阻塞而不屈服于事件循环时,程序中的任何其他内容都无法执行,这可能不是您想要的。如果确实需要执行长时间的阻塞操作,则应尝试使用^{} 在线程或进程池中运行该操作,这将避免阻塞事件循环:
谢谢你的回答。如果运行
coroutine
不是一个硬性要求,那么这里有一个经过修改的、更紧凑的版本奇怪的是,我的
Python 3.5.2
中的一点调试表明,将None
作为执行器传递会导致创建_default_executor
,如下所示:我看到的超时处理示例非常简单。考虑到现实情况,我的应用程序要复杂一些。顺序是:
为了实现上述所有功能,在保持事件循环运行的同时,生成的代码包含以下代码:
相关问题 更多 >
编程相关推荐