使用 Asyncio + Aiohttp 将一个请求的输出用作下一个请求的参数

Output of one request used as a parameter in next request using Asyncio + Aiohttp

我是异步编程、Asyncio、Aiohttp 世界的新手。

我有多个请求,其中 - 第一个请求的输出被用作第二个请求的参数。

到目前为止我已经尝试了这么多-

import aiohttp
import asyncio


async def get_response(session, url, params):
    async with session.get(url=url, params=params) as response:
        response = await response.json()
        return response['output']


async def main():

    tasks = []

    url = "https://example.api.com/"

    url_1 = url + 'path_1'
    url_2 = url + 'path_2'

    params = {'name': "Hello"}

    async with aiohttp.ClientSession() as session:

        a1 = get_response(session, url_1, params)
        tasks.append(a1)

        params = {'name': a1}
        b1 = get_response(session, url_2, params)
        tasks.append(b1)

        responses = await asyncio.gather(*tasks, return_exceptions=True)

        print(responses)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

我收到这个很明显的错误 -

TypeError("Invalid variable type: value should be str, int or float, got <coroutine object get_response at 0x00000000037FA6C0> of type <class 'coroutine'>")

那么如何将第一个请求的输出而不是协程对象传递给第二个请求 -

params = {'name': a1}
b1 = get_response(session, url_2, params)

如果第二个需要第一个协程的结果,那么你不能运行两个协程并行,你需要等待响应第一个。例如:

async def get_both(session, url_1, url_2, params_1):
    a1 = await get_response(session, url_1, params_1)
    params_2 = {'name': a1}
    b1 = await get_response(session, url_2, params_2)
    return a1, b1  # or just b1 if you don't need a1

您的 main() 将如下所示:

async def main():
    url = "https://example.api.com/"
    url_1 = url + 'path_1'
    url_2 = url + 'path_2'
    params = {'name': "Hello"}

    async with aiohttp.ClientSession() as session:
        responses = await get_both(session, url_1, url_2, params)
        print(responses)

当然,您不会得到并行提取,但这是一个请求依赖于另一个请求的结果这一事实的直接结果。您可以轻松地做的是并行化 get_both 的多个实例 - 例如如果 url_1url_2 是列表,你可以这样做:

async def main():
    url_list_1 = [...]
    url_list_2 = [...]
    params = {'name': "Hello"}

    async with aiohttp.ClientSession() as session:
        coros = [get_both(session, url_1, url_2, params)
                 for url_1, url_2 in zip(url_list_1, url_list_2)]
        all_responses = await asyncio.gather(*coros)
        print(all_responses)