【发布时间】:2021-07-07 23:57:49
【问题描述】:
我对@987654321@ 还很陌生,我设法用它完成了一些请求。我创建了一个函数fetch_all(),它接收查询列表(URL)和先前使用asyncio 创建的循环作为参数,并调用函数fetch(),以JSON 格式获取每个查询的结果:
import aiohttp
import asyncio
import ssl
import nest_asyncio
nest_asyncio.apply()
async def fetch(session, url):
async with session.get(url, ssl=ssl.SSLContext()) as response:
return await response.json()
async def fetch_all(urls, loop):
async with aiohttp.ClientSession(loop=loop) as session:
return await asyncio.gather(*[fetch(session, url) for url in urls], return_exceptions=True)
if __name__ == '__main__':
loop = asyncio.get_event_loop()
results = loop.run_until_complete(fetch_all(queries, loop))
这可以正常工作,我将results 中的查询结果作为 JSON(字典)列表。但这是我的问题:有时,某些结果(RuntimeError、aiohttp.client_exceptions.ClientConnectorError 等)出现错误,而不是 JSON。我猜这些是一次性错误,因为如果我单独重做查询,我会得到想要的结果。因此,我想出了一个while 循环来检查哪些结果不是字典并重做它们的查询:我用查询及其索引初始化repeat_queries、error_index 和results,并应用run_until_complete()。然后我保存作为字典的每个结果并更新剩下的查询列表及其索引:
repeat_queries = queries
error_index = list(range(len(repeat_queries)))
results = error_index
while error_index:
if __name__ == '__main__':
loop = asyncio.get_event_loop()
repeat_results = loop.run_until_complete(fetch_all(repeat_queries, loop))
for i, rr in zip(error_index, repeat_results):
results[i] = rr
error_index = [i for i in range(len(results)) if not isinstance(results[i], dict)]
repeat_queries = [repeat_queries[i] for i in error_index]
但是,由于 asyncio 循环是异步的,error_index 和 repeat_queries 更新会在 run_until_complete() 完成之前执行,并且循环会继续运行之前迭代中已经投射的查询,从而导致一个(几乎)无限的while 循环。
因此,我的问题是:
有什么办法可以强制在loop.run_until_complete() 完成后执行某些代码?
我在 stackoverflow 中看到了一些类似的问题,但我无法应用他们的任何答案。
【问题讨论】:
-
我认为你过度复杂了一些代码 - 你可以使用
for i, rr, enumerate(repeat_results)而不是使用list(range(len(repeat_queries)))。您可以在一个for-loop 中完成所有操作,而不是使用一个for-loop 创建results[i], otherfor-loop to createerrorn_index, and thirdfor-loop to getrepeat_queries`。 -
你应该运行
if __name__ == '__main__':中的所有代码 -
我会在
fetch()内使用while-loop 来一次重复它——而不是等待所有数据结束。最终我会使用循环for _ in range(3): ... break重复它 3 次 - 如果有问题 - 如果它得到正确的数据,则使用break。 -
如果您看到类似的问题,那么您可以添加有问题的链接(不在评论中)
标签: python asynchronous python-asyncio synchronous aiohttp