Что не так с этим асинхронным кодом aiohttp?

Для следующего кода, использующего 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 может быть вызвана до того, как ответ будет прочитан)

1 ответ

Решение

with это менеджер контекста, он запускает некоторый код до и после любых операторов в своем блоке, обычно бухгалтерия. Смысл, твой первый recv Функция, скорее всего, ожидает в будущем, что ссылается на уже закрытое соединение, или что-то в этом роде.

Допустим, у вас есть код, который выглядит следующим образом:

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

Вот что он делает примерно:

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

И это эквивалентно тому, что вы делаете в первом примере:

file = open()
file.close()
...
file.read()
Другие вопросы по тегам