我编写了一个从Strava的公共API下载活动ID的功能。
该函数迭代API页面,收集ID,并在从已标识为最后一个的页面中收集ID后停止运行:
import requests
def get_activity_ids():
"""Returns a list of activity ids for the token owner"""
ids = []
params = {
'page': 1,
'per_page':200,
'access_token':'1111111',
}
while True:
r = requests.get('https://www.strava.com/api/v3/athlete/activities', params).json()
if len(r) == 0:
break
else:
ids += [activity['id'] for activity in r]
if len(r) < 200: # if last page
break
print('PAGE: {}, response length: {}'.format(params['page'], len(r)))
params['page'] += 1
return ids
我现在想将此功能转换为异步功能。 到目前为止,我明白了:
import asyncio
import concurrent.futures
import requests
def get_ids():
ids = []
async def main():
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor:
loop = asyncio.get_event_loop()
futures = [
loop.run_in_executor(
executor,
requests.get,
'https://www.strava.com/api/v3/athlete/activities?page={page}&per_page=200&access_token=111111111'.format(page=page)
)
for page in range(1,4)
]
for response in await asyncio.gather(*futures):
for activity in response.json():
ids.append(activity['id'])
pass
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
return ids
但是我不知道如何将上一个函数(while True
块)中最后一页逻辑的标识合并到此。
所以我需要以某种逻辑替换for i in range(1,4)
。
有人知道该怎么做吗?
答案 0 :(得分:2)
您正在尝试并行化无法并行运行的操作。在知道下一个请求是否应该发生之前,每个请求都需要等待上一个请求完成。这本质上是顺序的。
如果可以接受不存在的页面请求,则可以并行提交有限数量的请求,在先前的请求完成时发出更多请求,并在发现结尾时停止。不过,这不会像列表理解和gather
那样简单。