Python 遍历列表以获取 api 在 asyncio 中调用并保存结果

Python loop through list to get api call in asyncio and save results

我还没有完全理解 asyncio 和 aiohttp 是如何工作的。

我正在尝试从 url 列表发出一堆异步 api 请求并将它们保存为变量,以便稍后处理它们。

到目前为止,我正在生成没问题的列表并设置请求框架。

urls = []
for i in range(0,20):
    urls.append('https://api.binance.com/api/v1/klines?symbol={}&interval= 
    {}&limit={}'.format(pairs_list_pairs[i],time_period,
            pull_limit))

import asyncio
import aiohttp


async def request(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.text()


async def main():
    results = await asyncio.gather(
             request(urls[0]),
             request(urls[1]),
    )
    print(len(results))
    print(results)



loop = asyncio.get_event_loop()
try:
    loop.run_until_complete(main())
    loop.run_until_complete(loop.shutdown_asyncgens())
finally:
    loop.close()

如果我使用索引(如下所示)手动输入我的请求,我可以提出请求。但问题是我的列表中有超过 100 api 条我不想手动输入的请求。我怎样才能遍历我的列表?另外,如何将结果保存到变量中?当脚本结束时,它不会在任何地方保存 "results"。

async def main():
    results = await asyncio.gather(
             request(urls[0]),
             request(urls[1]),
    )
    print(len(results))
    print(results)

下面是一些用于复制代码的示例 url:

[
 'https://api.binance.com/api/v1/klines?symbol=ETHBTC&interval=15m&limit=1',
 'https://api.binance.com/api/v1/klines?symbol=LTCBTC&interval=15m&limit=1',
 'https://api.binance.com/api/v1/klines?symbol=BNBBTC&interval=15m&limit=1',
 'https://api.binance.com/api/v1/klines?symbol=NEOBTC&interval=15m&limit=1',
]

使用 gather 和辅助函数 (request) 只会使一个非常简单的任务变得更加复杂和难以处理。您可以简单地在所有带有循环的单个请求中使用相同的 ClientSession,同时将每个响应保存到结果列表中。

async def main():
    results = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            async with session.get(url) as resp:
                results.append(await resp.text())
    print(len(results))
    print(results)

对于你问题的另一部分,当你说:

When the script ends it does not save "results" anywhere.

如果您想在 main 协同程序之外访问 results,您只需添加一条 return 语句即可。

main末尾添加:

return results

并改变

loop.run_until_complete(main())
# into:
results = loop.run_until_complete(main())

要将可变数量的参数传递给 gather,请使用 * 函数参数语法:

results = await asyncio.gather(*[request(u) for u in urls])

请注意,f(*args) 是一项标准 Python 功能,用于调用 f 并在 运行 时计算位置参数。

results 将在所有请求完成后可用,并且它们将以与 URL 相同的顺序出现在列表中。然后你可以从 main 中 return 它们,这将导致它们被 run_until_complete 编辑 return。

此外,如果您只创建一次会话并为所有请求重用它,您将获得更好的性能,例如通过将其作为第二个参数传递给 request 函数。