Python中的asyncio库盾函数?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。
<强>盾强>
asyncio。盾,用它可以屏蔽取消操作。一直到这里,我们还没有见识过任务的取消。看一个例子:
拷贝:,loop =, asyncio.get_event_loop ()=:拷贝,task1 loop.create_task (())=:拷贝,task2 loop.create_task (b ()) 拷贝:task1.cancel () :真的 拷贝:await asyncio.gather (task1, task2) Suspending Suspending b --------------------------------------------------------------------------- CancelledError ,,,,,,,,,,,,,,,,,,,,,,,,,,, Traceback (most recent  call 最后) cell_name async-def-wrapper拷贝() CancelledError:
在上面的例子中,task1被取消了后再用asyncio。收集收集结果,直接抛CancelledError错误了。这里有个细节,收集支持return_exceptions参数:
拷贝:,await asyncio.gather (task1, task2,, return_exceptions=True) :,(concurrent.futures._base.CancelledError (), & # 39; b # 39;]
可以看的到,task2依然会执行完成,但是task1的返回值是一个CancelledError错误,也就是任务被取消了。如果一个创建后就不希望被任何情况取消,可以使用asyncio。盾保护任务能顺利完成。不过要注意一个陷阱,先看错误的写法:
拷贝:,task1 =, asyncio.shield (())=:拷贝,task2 loop.create_task (b ()) 拷贝:task1.cancel () :真的 拷贝:await asyncio.gather (task1, task2,, return_exceptions=True) Suspending Suspending b Resuming b :,(concurrent.futures._base.CancelledError (), & # 39; b # 39;]
可以看到依然是CancelledError错误,且协程一个未执行完成,正确的用法是这样的:
拷贝:,task1 =, asyncio.shield (())=:拷贝,task2 loop.create_task (b ())=:拷贝,ts asyncio.gather (task1, task2,, return_exceptions=True) 拷贝:task1.cancel () :真的 拷贝:await ts Suspending Suspending b Resuming Resuming b :,(concurrent.futures._base.CancelledError (), & # 39; b # 39;]
可以看到虽然结果是一个CancelledError错误,但是看输出能确认协程实际上是执行了的,所以正确步骤是:
先创建GatheringFuture对象ts
取消任务
等待ts
asynccontextmanager
如果你了Python,解之前可能听过或者用过contextmanager,一个上下文管理器。通过一个计时的例子就理解它的作用:
得到contextlib import contextmanager async def (): ,,,await asyncio.sleep (3) ,,,return & # 39;一个# 39; async def b (): ,,,await asyncio.sleep (1) ,,,return & # 39; b # 39; async def  s1 (): ,,,return await asyncio.gather ((),, b ()) @contextmanager def 定时(函数): ,,,start =, time.perf_counter () ,,,油品收率asyncio.run (func ()) ,,,print (f # 39;成本:{time.perf_counter(),背后,开始}& # 39;)
定时函数用了contextmanager装饰器,把协程的运行结果产量出来,执行结束后还计算了耗时:
拷贝:得到contextmanager import * 拷贝:with 定时(s1), as 房车: …:,,,,,印刷(f # 39;结果:,{房车}& # 39;) …: 结果:,(& # 39;一个# 39;,,& # 39;b # 39;】 成本:3.0052654459999992
大家先体会一下。在Python 3.7添加了asynccontextmanager,也就是异步版本的contextmanager,适合异步函数的执行,上例可以这么改:
@asynccontextmanager async def  async_timed(函数): ,,,start =, time.perf_counter () ,,,油品收率await func () ,,,print (f # 39;成本:{time.perf_counter(),背后,开始}& # 39;) async def main (): ,,,async with async_timed (s1), as 房车: ,,,,,,,印刷(f # 39;结果:,{房车}& # 39;) 拷贝:asyncio.run (main ()) 结果:,(& # 39;一个# 39;,,& # 39;b # 39;】 成本:3.00414147500004,
异步版本的,要用异步,另外要注意收益率等待func()这句,相当于产量+等待func ()
PS: contextmanager和asynccontextmanager最好的理解方法是去看源码注释
关于Python中的asyncio库盾函数问题的解答就分享到这里了,希望以上内容可以对大家有一定的帮助,如果你还有很多疑惑没有解开,可以关注行业资讯频道了解更多相关知识。