如果我在 python3 解释器上运行它:
import asyncio
@asyncio.coroutine
def wait(n):
asyncio.sleep(n)
loop = asyncio.get_event_loop()
fut = asyncio.async(wait(10))
fut.add_done_callback(lambda x: print('Done'))
asyncio.Task.all_tasks()
我得到以下结果:
{<Task pending coro=<coro() running at /usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/lib/python3.4/asyncio/coroutines.py:139> cb=[<lambda>() at <ipython-input-5-c72c2da2ffa4>:1]>}
现在,如果我运行fut.cancel()
,我会返回True
。但是输入fut
会返回任务的表示,表明它正在取消:
<Task cancelling coro=<coro() running at /usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/lib/python3.4/asyncio/coroutines.py:139> cb=[<lambda>() at <ipython-input-5-c72c2da2ffa4>:1]>
任务从未实际取消(fut.cancelled()
永不返回True
)
为什么不取消?
答案 0 :(得分:4)
调用task.cancel()
仅调度在下次运行事件循环时要取消的任务;它不会立即取消任务,甚至可以保证在事件循环运行下一次迭代时实际取消该任务。这一切都描述为in the documentation:
取消()
请求此任务取消。
这会安排将
CancelledError
扔进被包裹的地方 通过事件循环在下一个循环中的协程。那个协程 有机会清理甚至拒绝使用请求 尝试/除外/最后。与
Future.cancel()
不同,这并不能保证任务的完成 取消:异常可能被抓住并采取行动,推迟 取消任务或完全阻止取消。该 任务也可以返回值或引发不同的异常。调用此方法后,
cancelled()
将不会立即返回True
(除非该任务已被取消)。任务将标记为 当包装的协程以CancelledError
终止时取消 异常(即使未调用cancel()
)。
在您的情况下,您实际上从未启动过事件循环,因此任务永远不会被取消。您需要致电loop.run_until_complete(fut)
(或loop.run_forever()
,虽然这不是这个特定情况的最佳选择),但任务实际上最终会被取消。
此外,对于它的价值,使用实际脚本而不是解释器来测试asyncio
代码通常更容易,因为必须不断重写协同程序并启动/停止事件循环会变得乏味。
答案 1 :(得分:0)
在解释器中使用 asyncio 测试很棘手,因为python需要保持事件循环不断轮询其任务。
所以测试 asyncio 的一些建议是:
loop.run_forever()
,以便执行所有任务。loop.run_until_complete(coro())
。yield from
前面有asyncio.sleep(n)
所以它实际上可以运行。当前代码返回一个生成器并且什么都不做。