множественный запрос на получение с использованием asyncio и aiohttp с периодом ожидания - PullRequest
0 голосов
/ 04 февраля 2019

Проблема - Я пытаюсь сделать несколько запросов на получение разных URL-адресов, используя asyncio, async_timeout и aiohttp.Я просто хочу выполнить обработку покоя либо после завершения всего запроса на получение, либо по истечении времени ожидания, в зависимости от того, что произойдет раньше.Если все задачи не завершаются в течение указанного периода _DEFAULT_TIME_OUT, то независимо от того, завершен ли запрос get, выполняются только с ними.

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

async def get(self, session, url, attributes):
        timeout_period = self._DEFAULT_TIME_OUT)
        try:
            with async_timeout.timeout(timeout_period) as timeout:
                async with session.get(url) as response:
                    self.urls[url] = await response.content.read()
                    response.release()
                print("---{}---".format(url))
                raise asyncio.TimeoutError()
        except asyncio.TimeoutError:
            pass

async def http_request(self, even_loop):
    tasks = []
    async with aiohttp.ClientSession(loop=even_loop) as session:
        for url in all_urls:
            tasks.append(self.get(session, url, attributes))
        await asyncio.gather(*tasks)
        print("Do something else")

1 Ответ

0 голосов
/ 04 февраля 2019

В этом примере показано, как работать с async_timeout и получить информацию о задачах:

import aiohttp
import asyncio
import async_timeout


async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.json()


async def main():
    timeout = 3.5

    tasks = [
        asyncio.create_task(get(f'http://httpbin.org/delay/{delay}'))
        for delay
        in range(1, 6)
    ]

    try:
        with async_timeout.timeout(timeout):
            await asyncio.gather(*tasks)
    except asyncio.TimeoutError:
        pass
    finally:
        for i, task in enumerate(tasks):
            if task.done() and not task.cancelled():
                print(f'Task is finished: {task.result()["url"]}.')
            else:
                print(f'Task hasn\'t been finished.')


asyncio.run(main())

Результат:

Task is finished: http://httpbin.org/delay/1.
Task is finished: http://httpbin.org/delay/2.
Task is finished: http://httpbin.org/delay/3.
Task hasn't been finished.
Task hasn't been finished.

Вы можетепоиграйте с timeout и delay переменными, чтобы увидеть, что все работает как положено:

timeout = 10

tasks = [
    asyncio.create_task(get(f'http://httpbin.org/delay/{delay}'))
    for delay
    in (1, 1, 1)
]

Будет завершено вскоре через 1 сек.со всеми выполненными задачами.

...