英文:
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) -> 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)
Response:
<coroutine object as_completed.<locals>.wait_for_one at 0x938742>
ClientResponse(...)[200 OK]
<CIMultiDictProxy>('Content-Type':'application/json', 'Content-Length':'803',.....)
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) -> 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) -> int:
return await session.get(url)
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):
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('https://www.example.com'),
session.get('https://www.example.com'),
session.get('https://www.example.com')]
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())
更新
如果我注释掉打印返回的内容,只打印响应,我会得到:
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '592259', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1D2E)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '314797', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1DCD)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '592259', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1D2E)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
如果我执行 print(await response.text())
,那么我会看到:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
<details>
<summary>英文:</summary>
The problem is you have:
```python
async def fetch_status(session: ClientSession, url: str) -> 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) -> int:
return await session.get(url)
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):
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('https://www.example.com'),
session.get('https://www.example.com'),
session.get('https://www.example.com')]
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:
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '592259', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1D2E)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '314797', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1DCD)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
<ClientResponse(https://www.example.com) [200 OK]>
<CIMultiDictProxy('Content-Encoding': 'gzip', 'Accept-Ranges': 'bytes', 'Age': '592259', 'Cache-Control': 'max-age=604800', 'Content-Type': 'text/html; charset=UTF-8', 'Date': 'Mon, 10 Jul 2023 17:05:53 GMT', 'Etag': '"3147526947"', 'Expires': 'Mon, 17 Jul 2023 17:05:53 GMT', 'Last-Modified': 'Thu, 17 Oct 2019 07:18:26 GMT', 'Server': 'ECS (nyb/1D2E)', 'Vary': 'Accept-Encoding', 'X-Cache': 'HIT', 'Content-Length': '648')>
If I execute print(await response.text())
, then I see:
<!doctype html>
<html>
<head>
<title>Example Domain</title>
<meta charset="utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
body {
background-color: #f0f0f2;
margin: 0;
padding: 0;
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", 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;
}
}
</style>
</head>
<body>
<div>
<h1>Example Domain</h1>
<p>This domain is for use in illustrative examples in documents. You may use this
domain in literature without prior coordination or asking for permission.</p>
<p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论