【问题标题】:asyncio aiohttp - client read of closed file errorasyncio aiohttp - 客户端读取已关闭文件错误
【发布时间】:2018-12-11 15:31:12
【问题描述】:

这是代码:

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)]))

我收到一个错误:

ValueError: read of closed file

但是,如果我将 open() 调用移到 start() 函数内部,它就可以工作。但我不想多次打开文件。

【问题讨论】:

  • 是的,尽管我仍然想知道为什么相同的代码可以与requests 一起使用。使用files= 参数
  • 好问题。它真的工作(正确地),还是只是没有引发异常?也许requests 将文件读到最后,但没有关闭它,因此除了第一个请求之外的所有请求都使用零长度数据。

标签: python python-requests python-asyncio aiohttp


【解决方案1】:

问题在于open(...) 返回一个file object,并且您将相同的文件对象传递给您在顶层创建的所有start() 协程。碰巧最先调度的协程实例会将文件对象作为data参数的一部分传递给session.post()session.post()会将文件读到最后并关闭文件对象。下一个 start() 协程将尝试从现在关闭的对象中读取,这将引发异常。

要在不多次打开文件的情况下解决问题,您需要确保将数据实际读取为字节对象:

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

这会将相同的字节对象传递给所有协程,这应该按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-08
    • 2018-10-22
    • 2017-07-26
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多