如何将更复杂的逻辑纳入异步期货列表理解

时间:2019-01-18 19:39:25

标签: python python-requests python-asyncio

我编写了一个从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)

有人知道该怎么做吗?

1 个答案:

答案 0 :(得分:2)

您正在尝试并行化无法并行运行的操作。在知道下一个请求是否应该发生之前,每个请求都需要等待上一个请求完成。这本质上是顺序的。

如果可以接受不存在的页面请求,则可以并行提交有限数量的请求,在先前的请求完成时发出更多请求,并在发现结尾时停止。不过,这不会像列表理解和gather那样简单。