摘要:整理一下asyncio.shield函数的使用

使用

说到底我不明白asyncio.shield函数到底有什么用,真的可以保护协程函数执行不被取消?未必......只有该协程不能是最后一个被loop循环执行的协程时,才能使用shield函数防止协程被取消......。但是复杂环境我怎么知道协程什么时候被执行....看下面这个例子就知道了。

例子

例子1:可以看到使用asyncio.shield保护task1不被取消,然后使用task1.cancel()取消task1,但是task1依然可以执行。

import asyncio
async def a():
    print("a-1执行")
    await asyncio.sleep(1)
    print("a-2执行")
    return 'A'

async def b():
    await asyncio.sleep(3)
    print("b-1执行")
    return 'B'

loop = asyncio.get_event_loop()
task1 = asyncio.shield(a())
task2 = loop.create_task(b())
async def main():
    f = asyncio.gather(task1, task2, return_exceptions=True)
    task1.cancel()
    a = await f
    print(a)
loop.run_until_complete(main())

'''
运行结果:
a-1执行
a-2执行
b-1执行
[CancelledError(), 'B']
'''

例子2:把代码的部分改成下面

import asyncio
async def a():
    print("a-1执行")
    await asyncio.sleep(4)
    print("a-2执行")
    return 'A'

async def b():
    await asyncio.sleep(1)
    print("b-1执行")
    return 'B'

loop = asyncio.get_event_loop()
task1 = asyncio.shield(a())
task2 = loop.create_task(b())
async def main():
    f = asyncio.gather(task1, task2, return_exceptions=True)
    task1.cancel()
    a = await f
    print(a)
loop.run_until_complete(main())

'''
运行结果:
a-1执行
b-1执行
[CancelledError(), 'B']
'''

例子1和例子2做对比,可以发现使用shield函数防止协程被取消时,该协程不能是最后一个被loop循环执行的协程。
原因:懒得去翻源码了,有兴趣自己看实现去。