使用xlrd打开BytesIO(xlsx)

时间:2016-04-07 09:57:21

标签: python xlrd

我正在使用Django,需要阅读上传的xlsx文件的工作表和单元格。应该可以使用xlrd,但因为文件必须保留在内存中,并且可能无法保存到某个位置,我不知道如何继续。

这种情况下的起点是一个带有上传输入和提交按钮的网页。提交时,文件被request.FILES['xlsx_file'].file捕获并发送到处理类,该处理类必须提取所有重要数据以供进一步处理。

request.FILES['xlsx_file'].file的类型是BytesIO,由于没有getitem方法,xlrd无法读取该类型。

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

3 个答案:

答案 0 :(得分:2)

I'm moving my comment into an answer of it's own. It related to the example code (which includes decoding) given in the updated question:

Ok, thanks for your pointers. I downloaded xlrd and tested it locally. It seems the best way to go here is to pass it a string ie. open_workbook(file_contents=xlsx_file.read().decode(encoding=file_enc, errors='replace')). I misunderstood the docs, but I'm positive that file_contents= will work with a string.

答案 1 :(得分:1)

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

答案 2 :(得分:0)

我遇到了类似的问题,但在我的情况下,我需要对用户下载xls文件的Djano应用进行单元测试。

使用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