这个async aiohttp代码有什么问题?

3

以下是使用aiohttp的代码:

async def send(self, msg, url):
    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=msg) as response:
            self._msg = response.read()

async def recv(self):
    return await self._msg

它能够正常运行...大部分时间,但偶尔(实际上是频繁地)会出现各种异常 - 通常是截断响应或连接已关闭的异常。

相比之下,以下代码完美运行:

async def send(self, msg, url):
    async with aiohttp.ClientSession() as session:
        async with session.post(url, data=msg) as response:
            self._msg = await response.read()

async def recv(self):
    return self._msg

我想知道为什么第二个版本在我的情况下技术上是不正确的,我需要修复它。(它不正确的原因是在读取响应之前可能会调用recv函数)

“这是不正确的,因为在读取响应之前可能会调用recv函数” - 如果在第一个版本中调用 self._msg 尚未设置,那么它将等待什么? - user2357112
确切地说,我所拥有的代码恰好在send完成之后很久才调用recv。但是,这是一个非常好的观点,事实证明两个版本都基本上是错误的。你能提出一种修复方法,同时仍然将“send”和“recv”在概念上分开吗? - Arafangion
虽然我很感激修复,但我真正想要的答案是理解这两个代码示例之间的区别。 - Arafangion
1个回答

2

with 是一个上下文管理器,它在其块中的任何语句之前和之后运行一些代码,通常用于账务记录。这意味着,你的第一个 recv 函数很可能会等待一个未来的引用,该未来的引用指向已经关闭的连接,或者类似这样的情况。

假设你有一些像这样的代码:

with open(...) as file:
    file.read()

大致上说,它的功能如下:

file = open(...)
file.read()
file.close()

这就是你在第一个例子中所做的等效操作:

file = open()
file.close()
...
file.read()

那会使未来失效吗? - Arafangion
1
我不确定你所说的“使未来失效”具体指什么,但基本上,整个问题并不是asyncio的问题。这是从已关闭的套接字读取或发生在response.read()深处的其他问题。 - Alex Undefined
1
更新了答案。 - Alex Undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接