Openpyxl 使用优化只写显着增加 excel 文件的磁盘使用
Openpyxl using optimized write-only significantly increases the disk usage of the excel file
一个大型生产程序正在使用 Openpyxl 将大量数据导出到电子表格中。对于大型系统来说非常慢(例如:4 小时)。我意识到我可以使用 Openpyxl 优化的只写模式来显着加快时间(~7 秒)。据我所知,这是正确完成的,电子表格包含相同的数据,并且根据 LibreOffice,具有完全相同的单元格数。
问题出在excel文件的磁盘占用上。旧的、较慢的方法使用 ~4MB 的磁盘 space,而新的优化模式使用 ~8MB。
我调查了什么
- 对于大量重复字符串(很普遍)共享字符串引用的方式可能有所不同。我发现磁盘 space 在大量相同的字符串之间使用,并且在两种方法之间使用大量独特的字符串没有变化。 (下面使用的代码)
from openpyxl import Workbook
wb = Workbook(write_only=True)
ws = wb.create_sheet(title='mem')
for irow in range(10000):
ws.append(['hi' for i in range(200)])
wb.save('opt.xlsx')
#####################################################
wb2 = Workbook()
sheet = wb2.active
sheet.title = "mem2"
for irow in range(1, 10001):
for column in range(1, 201):
cell = sheet.cell(row=irow, column=column)
cell.value = 'hi'
wb2.save('nonopt.xlsx')
生成了相同大小的电子表格
- 在 LibreOffice 中打开电子表格,然后将其保存为 XML 格式会减少优化电子表格的数据大小,几乎与未优化的电子表格相匹配。
我正在寻找答案
由于保存电子表格减少了数据大小,我的想法是要么存在一些浪费的元数据,要么 LibreOffice 自动删除了许多空单元格。我无法理解它们是如何通过简单地切换到只写模式并将值存储在行列表而不是单元格 class 中来产生的。所以我在寻找:
如何检验我对数据使用的假设,因为我不太确定如何检查这些。
磁盘使用量较大的其他可能性
如果我测试字符串引用不正确。
如果确定确实需要代码本身,我可以尝试将它的一个小演示放在一起,但目前它与我无法共享的代码混在一起。我也无法分享电子表格。因此,我不希望 100% 的答案确定问题,但可能会引导我确认它并更新 post.
谢谢。
从 2.6 版开始,openpyxl 对所有内容都使用内联字符串,因为这允许流式传输工作表,速度更快,使用的内存更少。 XML 是完全有效的,但结果有点臃肿,它避免了管理重复字符串的需要。 MS Excel 和 OpenOffice 优化了字符串库,但这完全是可选的。输出文件的大小并不真正相关,但值得注意的是文件格式针对数字进行了优化,字符串和日期之类的东西绝对是第二个-class 公民。
查看电子表格的 xml 文件后(xlsx 是一个包含 xml 文件的 zip 文件夹),我发现其中包含许多空字符串,通常可以省略它们.
进一步挖掘后,我发现我用 ''
而不是 None
填充空单元格,解决这个问题就解决了。
一个大型生产程序正在使用 Openpyxl 将大量数据导出到电子表格中。对于大型系统来说非常慢(例如:4 小时)。我意识到我可以使用 Openpyxl 优化的只写模式来显着加快时间(~7 秒)。据我所知,这是正确完成的,电子表格包含相同的数据,并且根据 LibreOffice,具有完全相同的单元格数。
问题出在excel文件的磁盘占用上。旧的、较慢的方法使用 ~4MB 的磁盘 space,而新的优化模式使用 ~8MB。
我调查了什么
- 对于大量重复字符串(很普遍)共享字符串引用的方式可能有所不同。我发现磁盘 space 在大量相同的字符串之间使用,并且在两种方法之间使用大量独特的字符串没有变化。 (下面使用的代码)
from openpyxl import Workbook
wb = Workbook(write_only=True)
ws = wb.create_sheet(title='mem')
for irow in range(10000):
ws.append(['hi' for i in range(200)])
wb.save('opt.xlsx')
#####################################################
wb2 = Workbook()
sheet = wb2.active
sheet.title = "mem2"
for irow in range(1, 10001):
for column in range(1, 201):
cell = sheet.cell(row=irow, column=column)
cell.value = 'hi'
wb2.save('nonopt.xlsx')
生成了相同大小的电子表格
- 在 LibreOffice 中打开电子表格,然后将其保存为 XML 格式会减少优化电子表格的数据大小,几乎与未优化的电子表格相匹配。
我正在寻找答案
由于保存电子表格减少了数据大小,我的想法是要么存在一些浪费的元数据,要么 LibreOffice 自动删除了许多空单元格。我无法理解它们是如何通过简单地切换到只写模式并将值存储在行列表而不是单元格 class 中来产生的。所以我在寻找:
如何检验我对数据使用的假设,因为我不太确定如何检查这些。
磁盘使用量较大的其他可能性
如果我测试字符串引用不正确。
如果确定确实需要代码本身,我可以尝试将它的一个小演示放在一起,但目前它与我无法共享的代码混在一起。我也无法分享电子表格。因此,我不希望 100% 的答案确定问题,但可能会引导我确认它并更新 post.
谢谢。
从 2.6 版开始,openpyxl 对所有内容都使用内联字符串,因为这允许流式传输工作表,速度更快,使用的内存更少。 XML 是完全有效的,但结果有点臃肿,它避免了管理重复字符串的需要。 MS Excel 和 OpenOffice 优化了字符串库,但这完全是可选的。输出文件的大小并不真正相关,但值得注意的是文件格式针对数字进行了优化,字符串和日期之类的东西绝对是第二个-class 公民。
查看电子表格的 xml 文件后(xlsx 是一个包含 xml 文件的 zip 文件夹),我发现其中包含许多空字符串,通常可以省略它们.
进一步挖掘后,我发现我用 ''
而不是 None
填充空单元格,解决这个问题就解决了。