Aiohttp:`async with session.get(...)`块会阻塞,直到收到请求:为什么?

问题描述 投票:0回答:1

我剪下了以下代码:

import aiohttp
import asyncio

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.get("https://hub.dummyapis.com/delay?seconds=1") as r:
            print("Here!")
            text = await r.text()
            print(text)

asyncio.run(main())

我调用的网址只是等待一秒钟,然后返回一个

200

我以为

Here!
会立即打印,然后 1 秒会过去(或者可能会多一点,包括发送和接收请求的开销),然后文本将被打印。毕竟,我只是在
await
声明之后才
print("Here!")
。但事实并非如此,
Here!
仅在1秒后才被打印。所以我猜
async with session.get(...) as r
被阻塞了?我的问题:

  1. 这是怎么回事?等待收到回复是
    aiohttp
    的实现细节,还是我在这里误解了
    async
    ?我可以解锁
    session.get(...) as r
    吗?
  2. 更具体地说,我希望能够:
  • 首先发送请求,保存一个 Future/awaitable(或其他东西?),它将解析为稍后的响应。
  • 做一些工作 - 使用 Future/awaitable (特别是我想在请求进行时检查请求的状态)
  • 等待响应,然后返回

这可以用

aiohttp
吗?

python aiohttp
1个回答
0
投票

基本上这是一个内部实现。让我们研究一下 aiohttp 实现并从以下代码行开始

async with session.get("https://hub.dummyapis.com/delay?seconds=1") as r:

ClientSession

Get方法返回一个名为
_RequestContextManager
here的上下文管理器。如果你检查这个上下文管理器,它是从另一个名为
_BaseRequestContextManager
的上下文管理器继承的。
在这个上下文管理器的
__aenter__
中,它基本上等待请求的响应并返回响应。基本上,通过这一行,您已经向服务器发出了请求,并且服务器等待 1 秒才能获得响应。所以“这里!”是很正常的。 1秒后打印,因为上下文管理器内部的代码是在获得响应后执行的。如果您检查 text
ClientResponse
 方法,您可以看到该方法仅获取响应正文并对其进行解码。

© www.soinside.com 2019 - 2024. All rights reserved.