在一个异步函数返回True后终止事件循环



我有一个函数,它在不同的网页上查找一些信息,如果在目标网页上找到,则返回True,否则返回False。我想多次调用这个函数,每次都针对不同的网页,我希望每个函数都异步运行,我希望整个过程无限循环,直到这个函数的一个实例返回True。整个代码很长,所以为了让大家明白这一点,我将在下面简化它。这段代码很有效,可以做我想做的事情,但我想知道是否有更好或更干净的方法来实现同样的事情。我对异步很陌生,所以请放心:(

import asyncio

async def find_something(loop, item_to_find, website):
while True:
# Some code to check the contents of a webpage goes here
if item_to_find in website:
loop.stop()
return True
else:
return False
loop = asyncio.get_event_loop()
try:
asyncio.ensure_future(find_something(loop, item1, website1))
asyncio.ensure_future(find_something(loop, item2, website2))
asyncio.ensure_future(find_something(loop, item3, website3))
loop.run_forever()

except Exception as e:
pass
finally:
loop.close()

EDIT:我在代码中犯了一个错误,因为我只使用print语句进行了最初的测试,在这种情况下,返回False会终止while循环并自动结束函数调用,因此函数不会无限期地循环。因此,需要一个替代解决方案的更多理由。我可以完全删除while循环,并调用其内部的函数来进行递归循环,直到满足条件,或者除非满足所需条件,否则我不能返回任何内容,尽管

我相信asyncio.as_completed就是您想要的。它将在每个可获得的完成时返回结果。

import asyncio
async def find_something(item_to_find, website):
contents = await some_code_to_check_the_contents_of_a_webpage(website)
return item_to_find in contents
async def main():
aws = [
find_something(item1, website1),
find_something(item2, website2),
find_something(item3, website3),
]
for coro in asyncio.as_completed(aws):
was_found = await coro
if was_found:
return

asyncio.run(main())

需要注意的是,无法知道哪个对find_something的调用返回了True。如果这很重要,或者如果您需要取消任何挂起的任务,您可能需要从返回布尔值切换到返回一些值,这些值可以为您提供所需的信息(例如,参数(。然后,您可以将期货放在映射中,并取消任何您尚未看到的期货。这可能看起来像

aws = {
(item1, website1): asyncio.ensure_future(item1, website1),
(item2, website2): asyncio.ensure_future(item2, website2),
(item3, website3): asyncio.ensure_future(item3, website3),
}
for coro in asyncio.as_completed(aws.values()):
item, website, was_found = await coro
del aws[item, website]
if was_found:
for future in aws.values():
future.cancel()
return

最新更新