Async.io的`as_completed`返回ClientResponse协程而不是包含内容的实际响应。

huangapple go评论73阅读模式
英文:

Async.io as_completed returns ClientResponse coroutine instead of actual response with content

问题

我正在并发地向URL发出网络请求,并使用asyncio.as_completed()函数来获取响应,但当我尝试打印响应时,它返回的是协程表达式而不是实际的响应值。

以下是代码示例供参考:

import asyncio
import aiohttp
from aiohttp import ClientSession

async def fetch_status(session: ClientSession, url: str) -> int:
    async with session.get(url) as result:
        return result

async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [fetch_status(session, 'https://www.example.com'),
                    fetch_status(session, 'https://www.example.com'),
                    fetch_status(session, 'https://www.example.com')]

        for finished_task in asyncio.as_completed(fetchers):
            print(await finished_task)

响应:

<coroutine object as_completed.<locals>.wait_for_one at 0x938742>
ClientResponse(...)[200 OK]
<CIMultiDictProxy>('Content-Type':'application/json', 'Content-Length':'803',.....)

尝试了多种方法,但仍然报错"coroutine is not iterable"。请问是否可以帮助解决这个问题?提前感谢。

英文:

I'm making concurrent web requests to URL and i'm using asyncio.as_completed() function to get the response but when i try to print the response.it is giving coroutine expression and not the actual response values.

sharing the code below for reference

import asyncio
import aiohttp
from aiohttp import ClientSession

async def fetch_status(session: ClientSession, url: str) -&gt; int:
    async with session.get(url) as result:
        return result
    
async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;)]
 
        for finished_task in asyncio.as_completed(fetchers):
            print(await finished_task)

Response:

&lt;coroutine object as_completed.&lt;locals&gt;.wait_for_one at 0x938742&gt;
ClientResponse(...)[200 OK]
&lt;CIMultiDictProxy&gt;(&#39;Content-Type&#39;:&#39;application/json&#39;, &#39;Content-Length&#39;:&#39;803&#39;,.....)

Tried multiple ways but throwing coroutine is not iterable.could you please help me on this.Thanks in advance.

答案1

得分: 1

以下是您要翻译的代码部分:

async def fetch_status(session: ClientSession, url: str) -&gt; int:
    async with session.get(url) as result:
        return result

但如果您的意图是返回session.get调用的响应,请不要将其用作上下文管理器:

import asyncio
import aiohttp
from aiohttp import ClientSession

async def fetch_status(session: ClientSession, url: str) -&gt; int:
    return await session.get(url)

async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;)]

        for finished_task in asyncio.as_completed(fetchers):
            response = await finished_task
            print(response)
            print(await response.text())

asyncio.get_event_loop().run_until_complete(main())

更简单的方法是:

import asyncio
import aiohttp

async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [session.get(&#39;https://www.example.com&#39;),
                    session.get(&#39;https://www.example.com&#39;),
                    session.get(&#39;https://www.example.com&#39;)]

        for finished_task in asyncio.as_completed(fetchers):
            response = await finished_task
            print(response)
            # 实际内容:
            print(await response.text())

asyncio.get_event_loop().run_until_complete(main())

更新

如果我注释掉打印返回的内容,只打印响应,我会得到:

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;592259&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1D2E)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;314797&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1DCD)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;592259&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1D2E)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

如果我执行 print(await response.text()),那么我会看到:

&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Example Domain&lt;/title&gt;

    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
    &lt;style type=&quot;text/css&quot;&gt;
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, &quot;Segoe UI&quot;, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;

   

<details>
<summary>英文:</summary>

The problem is you have:

```python
async def fetch_status(session: ClientSession, url: str) -&gt; int:
    async with session.get(url) as result:
        return result

But if your intention is to return the response from the session.get call, do not use it as a context manager:

import asyncio
import aiohttp
from aiohttp import ClientSession

async def fetch_status(session: ClientSession, url: str) -&gt; int:
    return await session.get(url)

async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;),
                    fetch_status(session, &#39;https://www.example.com&#39;)]

        for finished_task in asyncio.as_completed(fetchers):
            response = await finished_task
            print(response)
            print(await response.text())

asyncio.get_event_loop().run_until_complete(main())

Simpler is to just do:

import asyncio
import aiohttp

async def main():
    async with aiohttp.ClientSession() as session:
        fetchers = [session.get(&#39;https://www.example.com&#39;),
                    session.get(&#39;https://www.example.com&#39;),
                    session.get(&#39;https://www.example.com&#39;)]

        for finished_task in asyncio.as_completed(fetchers):
            response = await finished_task
            print(response)
            # Actual content:
            print(await response.text())

asyncio.get_event_loop().run_until_complete(main())

Update

If I comment out printing the returned content and only print the response, I get:

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;592259&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1D2E)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;314797&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1DCD)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

&lt;ClientResponse(https://www.example.com) [200 OK]&gt;
&lt;CIMultiDictProxy(&#39;Content-Encoding&#39;: &#39;gzip&#39;, &#39;Accept-Ranges&#39;: &#39;bytes&#39;, &#39;Age&#39;: &#39;592259&#39;, &#39;Cache-Control&#39;: &#39;max-age=604800&#39;, &#39;Content-Type&#39;: &#39;text/html; charset=UTF-8&#39;, &#39;Date&#39;: &#39;Mon, 10 Jul 2023 17:05:53 GMT&#39;, &#39;Etag&#39;: &#39;&quot;3147526947&quot;&#39;, &#39;Expires&#39;: &#39;Mon, 17 Jul 2023 17:05:53 GMT&#39;, &#39;Last-Modified&#39;: &#39;Thu, 17 Oct 2019 07:18:26 GMT&#39;, &#39;Server&#39;: &#39;ECS (nyb/1D2E)&#39;, &#39;Vary&#39;: &#39;Accept-Encoding&#39;, &#39;X-Cache&#39;: &#39;HIT&#39;, &#39;Content-Length&#39;: &#39;648&#39;)&gt;

If I execute print(await response.text()), then I see:

&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Example Domain&lt;/title&gt;

    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;meta http-equiv=&quot;Content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot; /&gt;
    &lt;style type=&quot;text/css&quot;&gt;
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, &quot;Segoe UI&quot;, &quot;Open Sans&quot;, &quot;Helvetica Neue&quot;, Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    &lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div&gt;
    &lt;h1&gt;Example Domain&lt;/h1&gt;
    &lt;p&gt;This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.&lt;/p&gt;
    &lt;p&gt;&lt;a href=&quot;https://www.iana.org/domains/example&quot;&gt;More information...&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

huangapple
  • 本文由 发表于 2023年7月10日 22:50:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76654924.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定