Asyncio и aiohttp возвращают задание вместо результатов - PullRequest
0 голосов
/ 02 марта 2019

У меня есть скрипт для запуска параллельных запросов к API внутри класса.Тем не менее, результаты, которые я получаю, - это в основном задача, а не реальные результатыЕсть причина почему?

Я имитировал измененный клиентский код на https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html.

import asyncio
from aiohttp import ClientSession

class Requestor:
    async def _async_request(self, url, session, sema_sz=10):
        sema = asyncio.Semaphore(sema_sz)

        async with sema:
            async with session.get(url) as response:
                req = await response.json()

        return req

    async def _async_chunk_request(self, url, chunks, headers=None, sema_sz=10):
        async with ClientSession(headers=headers) as session:
            futures = [asyncio.ensure_future(self._async_request(url.format(chunk), session, sema_sz)) for chunk in chunks]
            responses = asyncio.gather(*futures)
            await responses

    def get_request(self, url, chunks):
        loop = asyncio.get_event_loop()
        bulk_req = asyncio.ensure_future(self._async_chunk_request(url, chunks))
        loop.run_until_complete(bulk_req)

        return bulk_req

На самом деле, Bulg_req - это переменная Task, а не результаты, и показывает это в PyCharm, Task finished coro=<Requestor._async_chunk_request() done, defined at ...

Когда я отлаживаю, я вижу, что req имеет полное и правильное значение ответа, так что с этим проблем нет.Я чувствую, что это как-то связано с фактическим сбором фьючерсов?

1 Ответ

0 голосов
/ 02 марта 2019

Ваш _chunk_request ничего не возвращает.

async def _chunk_request(...):
    ...
    ...
    await responses

Я сделал игрушку пример, пытающийся имитировать ваш процесс.Если я закончил _chunk_request, как вы, я получил тот же результат - законченное задание без результатов.Изменение _chunk_request для возврата что-то исправило это:

async def _chunk_request(...):
    ...
    ...
    return await responses

Если вам нужны только возвращаемые значения из задач, get_request должен вернуть результат вызова loop.run_until_complete().


Пример моей игрушки

import asyncio
import random
from pprint import pprint

async def response(n):
    asyncio.sleep(random.choice([1,3,5]))
    return f'i am {n}'

async def _request(n):
    req = await response(n)
    #print(req)
    return req

async def _chunk_request(chunks):
    futures = [asyncio.ensure_future(_request(chunk)) for chunk in chunks]
    #pprint(futures)
    responses = asyncio.gather(*futures, return_exceptions=True)
    #pprint(responses)
    return await responses

def get_request(chunks):
    loop = asyncio.get_event_loop()
    bulk_req = asyncio.ensure_future(_chunk_request(chunks))
    return loop.run_until_complete(bulk_req)

In [7]: result = get_request(range(1,6))

In [8]: print(result)
['i am 1', 'i am 2', 'i am 3', 'i am 4', 'i am 5']
...