Reputation: 6994
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
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