user3599803
user3599803

Reputation: 6994

asyncio aiohttp - client read of closed file error

This is the code:

import asyncio
import aiohttp
loop = asyncio.get_event_loop()
session = aiohttp.ClientSession(loop=loop)
data = {'file': open('test_img.jpg', 'rb')}

async def start():
        async with session.post("http://localhost", data=data) as response:
            text = await response.text()
            print(text)

loop.run_until_complete(asyncio.gather(*[start() for i in range(20)]))

I get an error:

ValueError: read of closed file

However if I move the open() call to inside the start() function, it works. But I don't want to open the file multiple times.

Upvotes: 1

Views: 666

Answers (1)

user4815162342
user4815162342

Reputation: 154906

The problem is that open(...) returns a file object, and you're passing the same file object to all start() coroutines you are creating at top-level. The coroutine instance that happens to be scheduled first will transfer the file object to session.post() as part of the data parameter, and session.post() will read the file to the end and close the file object. The next start() coroutine will try to read from the now-closed object which will raise the exception.

To fix the issue without opening the file multiple times, you need to make sure to actually read the data as a bytes object:

data = {'file': open('test_img.jpg', 'rb').read()}

This will pass the same bytes object to all coroutines, which should work as intended.

Upvotes: 3

Related Questions