【问题标题】:Output of one request used as a parameter in next request using Asyncio + Aiohttp使用 Asyncio + Aiohttp 将一个请求的输出用作下一个请求中的参数
【发布时间】:2021-02-13 19:10:12
【问题描述】:

我是 Async 编程、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)

【问题讨论】:

  • 您好,请问我的回答对您的问题有帮助吗?

标签: asynchronous async-await python-asyncio aiohttp


【解决方案1】:

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

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)

【讨论】:

    猜你喜欢
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    相关资源
    最近更新 更多