asyncio.as_completed(),目前几乎没有文献记录,它接受一个协程或期货的迭代,并按输入期货的完成顺序返回一个迭代的期货。
通常 ,您可以
await从
async函数内部遍历其结果和成员。
import asyncioasync def first(): await asyncio.sleep(5) return 'first'async def second(): await asyncio.sleep(1) return 'second'async def third(): await asyncio.sleep(3) return 'third'async def main(): for future in asyncio.as_completed([first(), second(), third()]): print(await future)loop = asyncio.get_event_loop()# Prints 'second', then 'third', then 'first'loop.run_until_complete(main())
…但是出于这个问题的目的,我们想要的是能够从普通的生成器中产生这些结果,以便普通的同步代码可以在不知道
async函数在内部被使用的情况下使用它们。我们可以
loop.run_until_complete()通过
as_completed看涨看涨期权来实现这一目标。
import asyncioasync def first(): await asyncio.sleep(5) return 'first'async def second(): await asyncio.sleep(1) return 'second'async def third(): await asyncio.sleep(3) return 'third'def ordinary_generator(): loop = asyncio.get_event_loop() for future in asyncio.as_completed([first(), second(), third()]): yield loop.run_until_complete(future)# Prints 'second', then 'third', then 'first'for element in ordinary_generator(): print(element)
这样一来,我们已经暴露了我们的异步代码,非异步土地在不需要调用者定义任何功能的方式
async,或者即使知道
ordinary_generator正在使用
asyncio引擎盖下。
作为
ordinary_generator()在某些情况下提供更大灵活性的一种替代实现,我们可以重复
asyncio.wait()使用该
FIRST_COMPLETED标志而不是循环进行
as_completed():
import concurrent.futuresdef ordinary_generator(): loop = asyncio.get_event_loop() pending = [first(), second(), third()] while pending: done, pending = loop.run_until_complete( asyncio.wait( pending, return_when=concurrent.futures.FIRST_COMPLETED ) ) for job in done: yield job.result()
这种维护
pending作业列表的方法的优势在于,我们可以对其进行调整,以将作业动态添加到
pending列表中。这在某些情况下很有用,在这种情况下,我们的异步作业会向队列中添加无法预测的其他作业数量,例如,在其访问的每个页面上跟随所有链接的网络蜘蛛。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)