Arafangion
Arafangion

Reputation: 11908

What's wrong with this async aiohttp code?

For the following code using 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

It works... Most of the time, but occasionally (frequently, actually) results in various exceptions - usually truncated responses, or a connection already being closed exception.

By contrast, the following works perfectly:

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

I would like to know why, as the second version is technically incorrect for my purposes and I need to fix it. (It is incorrect because the recv function might be called before the response has been read)

Upvotes: 3

Views: 348

Answers (1)

Alex Undefined
Alex Undefined

Reputation: 630

with is a context manager, it runs some code before and after any statements within it's block, bookkeeping usually. Meaning, your first recv function most likely awaits on a future that references an already closed connection, or something along these lines.

Let's say you have some code that looks like this:

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

This is what it does, roughly:

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

And this is the equivalent of what you're doing in your first example:

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

Upvotes: 2

Related Questions