Как включить более сложную логику в понимание списка асинхронных фьючерсов - PullRequest
0 голосов
/ 18 января 2019

Я написал функцию для загрузки идентификаторов действий из открытого API Strava.

Функция выполняет итерации страниц API, собирает идентификаторы и останавливается после получения идентификаторов со страницы, которую она идентифицировала как последнюю.:

 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 голосов
/ 18 января 2019

Вы пытаетесь распараллелить операции, которые нельзя запустить параллельно. Каждый запрос должен ждать завершения предыдущего, прежде чем вы узнаете, должен ли следующий запрос произойти. Это по своей сути последовательно.

Если у вас все в порядке с запросом несуществующих страниц, вы, вероятно, могли бы отправлять ограниченное количество запросов параллельно, делая больше запросов по завершении предыдущих запросов и останавливаясь, как только обнаружите, что достигли конца. Это не было бы так просто, как понимание списка и gather, хотя.

...