Asyncio和aiohttp返回任务而不是结果

时间:2019-03-01 21:09:51

标签: python asynchronous request python-asyncio aiohttp

我有一个脚本可以针对类中的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

bulk_req实际上是一个Task变量,而不是结果,并在PyCharm Task finished coro=<Requestor._async_chunk_request() done, defined at ...

中显示

当我调试时,我看到req具有完整而正确的响应值,因此没有问题。我觉得这与期货的实际收集有关吗?

1 个答案:

答案 0 :(得分:1)

您的_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']