如果我有一个协同程序,它运行一个不应该被取消的任务,我会将该任务包装为asyncio.shield()
.
似乎cancel
和shield
的行为不是我所期望的.如果我将一个任务包装在shield
中并取消它,那么await
ing协程将立即从await
语句返回,而不是像shield
所建议的那样等待任务完成.此外,与shield
一起运行的任务将继续运行,但它的future 将被取消,无法执行.
从docs人中:
除非包含它的协同程序被取消,否则在something()中运行的任务不会被取消.从某事的Angular 来看,取消没有发生.尽管它的调用者仍然被取消,所以"wait"表达式仍然会引发CanceledError.
这些文件并没有强烈暗示来电者可能在被叫人结束时被取消,这是我的问题的核心.
什么是正确的方法来阻止任务取消,然后等待任务完成再返回.
如果asyncio.shield()
在await
ed任务完成后提高了asyncio.CancelledError
,这会更有意义,但显然这里还有一些我不理解的 idea .
下面是一个简单的例子:
import asyncio
async def count(n):
for i in range(n):
print(i)
await asyncio.sleep(1)
async def t():
try:
await asyncio.shield(count(5))
except asyncio.CancelledError:
print('This gets called at 3, not 5')
return 42
async def c(ft):
await asyncio.sleep(3)
ft.cancel()
async def m():
ft = asyncio.ensure_future(t())
ct = asyncio.ensure_future(c(ft))
r = await ft
print(r)
loop = asyncio.get_event_loop()
loop.run_until_complete(m())
# Running loop forever continues to run shielded task
# but I'd rather not do that
#loop.run_forever()