Как инициировать следующий запрос перед передачей в асинхронный генератор в Python - PullRequest
0 голосов
/ 27 июня 2018

Я пытаюсь получить некоторые данные из разбитого на страницы API (особенно github, но API не имеет значения для этого вопроса). Я использую асинхронный генератор Python для получения каждой отдельной строки на каждой странице. Код выглядит примерно так:

async def get_data():
    cursor = None
    with aiohttp.ClientSession() as session:
        while True:
            async with session.get(build_url(cursor)):
                data = await response.json()

            yield from get_rows(data)

            if not has_next_page(data):
                return

            cursor = get_next_cursor(data)

Итак, это в основном работает. Однако один из незначительных недостатков заключается в том, что он не инициирует следующий запрос до тех пор, пока все строки не будут получены с текущей страницы. Есть ли хороший способ инициировать эту обработку внутри этого цикла, прежде чем начать давать? В частности, я хочу убедиться, что async with по-прежнему правильно оценивается при выполнении asyncio.ensure_future, который является API для инициирования фоновой работы.

1 Ответ

0 голосов
/ 27 июня 2018

Вам понадобится как минимум одна дополнительная сопрограмма, чтобы достичь этого, и соедините их с помощью asyncio.Queue:

async def get_data():
    queue = asyncio.Queue()

    async def fetch_all_pages():
        cursor = None
        with aiohttp.ClientSession() as session:
            while True:
                async with session.get(build_url(cursor)):
                    data = await response.json()

                await queue.put(data)

                if not has_next_page(data):
                    # signal the peer to exit
                    await queue.put(None)
                    break

                cursor = get_next_cursor(data)

    asyncio.ensure_future(fetch_all_pages())

    while True:
        data = await queue.get()
        if not data:
            break
        yield from get_rows(data)
...