我有asyncio.Task
我需要在一段时间后取消。在取消之前,任务需要进行一些清理。根据文档,我应该能够调用task.cancel或asyncio.wait_for(coroutine, delay)
并在协程中拦截asyncio.TimeoutError
,但以下示例不起作用。我已经尝试拦截其他错误,而是调用task.cancel
,但都没有效果。我是否误解了取消任务的工作原理?
@asyncio.coroutine
def toTimeout():
try:
i = 0
while True:
print("iteration ", i, "......"); i += 1
yield from asyncio.sleep(1)
except asyncio.TimeoutError:
print("timed out")
def main():
#... do some stuff
yield from asyncio.wait_for(toTimeout(), 10)
#... do some more stuff
asyncio.get_event_loop().run_until_complete(main())
asyncio.get_event_loop().run_forever()
答案 0 :(得分:4)
documentation for asyncio.wait_for
指定它将取消基础任务,然后从super.paintComponent
调用本身提升TimeoutError
:
返回Future或coroutine的结果。当发生超时时,它 取消任务并引发
wait_for
。
你认为任务取消正确can indeed be intercepted:
[
asyncio.TimeoutError
]安排将Task.cancel
投入到包装中 通过事件循环在下一个循环中的协程。那个协程 有机会清理甚至拒绝使用请求CancelledError
/try
/except
。
请注意,文档指定将finally
投入协程,而不是CancelledError
。
如果进行调整,事情会按照您的预期进行:
TimeoutError
输出:
import asyncio
@asyncio.coroutine
def toTimeout():
try:
i = 0
while True:
print("iteration ", i, "......"); i += 1
yield from asyncio.sleep(1)
except asyncio.CancelledError:
print("timed out")
def main():
#... do some stuff
yield from asyncio.wait_for(toTimeout(), 3)
#... do some more stuff
asyncio.get_event_loop().run_until_complete(main())
正如您所看到的,现在iteration 0 ......
iteration 1 ......
iteration 2 ......
timed out
Traceback (most recent call last):
File "aio.py", line 18, in <module>
asyncio.get_event_loop().run_until_complete(main())
File "/usr/lib/python3.4/asyncio/base_events.py", line 316, in run_until_complete
return future.result()
File "/usr/lib/python3.4/asyncio/futures.py", line 275, in result
raise self._exception
File "/usr/lib/python3.4/asyncio/tasks.py", line 238, in _step
result = next(coro)
File "aio.py", line 15, in main
yield from asyncio.wait_for(toTimeout(), 3)
File "/usr/lib/python3.4/asyncio/tasks.py", line 381, in wait_for
raise futures.TimeoutError()
concurrent.futures._base.TimeoutError
在'timed out'
引发TimeoutError
之前就会打印出来。