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

时间:2018-07-07 04:29:08

标签: python request python-asyncio aiohttp

我还不完全了解asyncio和aiohttp的工作原理。

我正在尝试从网址列表中发出一堆异步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请求。如何遍历清单?另外,如何将结果保存到变量中?脚本结束时,不会在任何地方保存“结果”。

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

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

[
 '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',
]

2 个答案:

答案 0 :(得分:3)

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

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

请注意,f(*args)是Python的标准功能,可以使用运行时计算出的位置参数来调用f

一旦完成所有请求,

results将可用,并且它们将以与URL相同的顺序出现在列表中。然后,您可以从main返回它们,这将导致run_until_complete返回它们。

此外,如果您仅创建一次会话并将其重用于所有请求(例如,通过将其作为第二个参数传递给request函数。

答案 1 :(得分: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)

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

  

脚本结束时,不会在任何地方保存“结果”。

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

main的末尾添加:

return results

并更改

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