使用xlrd打开BytesIO中的xlsx文件

7
我正在使用Django并需要读取上传的xlsx文件的工作表和单元格。虽然使用xlrd应该是可行的,但由于文件必须保留在内存中且可能不能保存到位置,我不确定如何继续进行。
在这种情况下,起点是一个带有上传输入和提交按钮的网页。当提交时,文件被捕获并发送到一个处理类中,该类必须提取所有重要数据以供进一步处理。 request.FILES['xlsx_file'].file的类型是BytesIO,而xlrd无法读取该类型,因为没有getitem方法。
将BytesIO转换为StringIO后,错误消息似乎仍然相同:'_io.StringIO' object has no attribute '__getitem__'
    file_enc = chardet.detect(xlsx_file.read(8))['encoding']
    xlsx_file.seek(0)

    sio = io.StringIO(xlsx_file.read().decode(encoding=file_enc, errors='replace'))
    workbook = xlrd.open_workbook(file_contents=sio)

那么您认为StringIO就足够了吗? - Adrian Z.
@Protagonist 是的,我已经在使用你建议的东西了。 - Adrian Z.
1
好的,谢谢你的指引。我已经下载了xlrd并在本地进行了测试。看起来这里最好的方法是传递一个字符串,例如open_workbook(file_contents=xlsx_file.read().decode(encoding=file_enc, errors='replace'))。我误解了文档,但我确信file_contents=可以与字符串一起使用。 - Protagonist
仅仅阅读看起来很好,但是我现在该如何测试是否有数据呢? - Adrian Z.
1
为此,您需要使用xlrd的API来读取工作簿的页面/单元格,其他任何内容都可以放在另一个问题中:)。另外,请如果解决了打开xlsx文件而不将其写入磁盘的问题,请接受我的答案! - Protagonist
显示剩余5条评论
3个回答

7

尝试使用xlrd.open_workbook(file_contents=request.FILES['xlsx_file'].read())


7
我将我的评论转化为一个独立的答案。这与更新后的问题中提供的示例代码(包括解码)有关:
好的,谢谢你的指点。我下载了xlrd并在本地测试了一下。似乎这里最好的方法是传递一个字符串,即open_workbook(file_contents=xlsx_file.read().decode(encoding=file_enc, errors='replace'))。我误解了文档,但我确定file_contents =将与一个字符串一起工作。

1
在这种情况下似乎不需要解码,因为读取的是ASCII类型,所以它可以正常工作。 - Adrian Z.
1
我仍然遇到这个错误:异常类型:TypeError 异常值: 不支持的操作数类型 <<:'str' 和 'int' - Abhimanyu

0

我遇到了类似的问题,但我的情况是需要对一个Django应用程序进行单元测试,并由用户下载xls文件。

使用StringIO的基本代码对我有用。

class myTest(TestCase):
    def test_download(self):
        response = self.client('...')
        f = StringIO.StringIO(response.content)
        book = xlrd.open_workbook(file_contents = f.getvalue() )
        ...
        #unit-tests here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接