MemoryError 使用 openpyxl 写入 500k+ 行
Posted
技术标签:
【中文标题】MemoryError 使用 openpyxl 写入 500k+ 行【英文标题】:MemoryError Using openpyxl to write 500k+ rows 【发布时间】:2015-03-04 02:38:37 【问题描述】:我有一个脚本,它使用 openpyxl 打开一个模板 xlsx 文件,然后对六张纸中的每一张进行制作,从脚本前面生成的列表中添加一些数据并更改单元格的格式。
我遇到的问题是,在某些情况下,我需要在一张纸上写 9 列和 500k+ 行,这给了我一个MemoryError
。
Traceback (most recent call last):
File "C:\python27\labs\labs\sqrdist\new_main_ui.py", line 667, in request_and_send_reports
x = sqr_pull.main()
File "C:\Python27\lib\site-packages\memory_profiler-0.32-py2.7.egg\memory_profiler.py", line 801, in wrapper
val = prof(func)(*args, **kwargs)
File "C:\Python27\lib\site-packages\memory_profiler-0.32-py2.7.egg\memory_profiler.py", line 445, in f
result = func(*args, **kwds)
File "C:\python27\labs\labs\sqrdist\sqr_pull.py", line 327, in main
os.remove(temp_attach_filepath)
File "build\bdist.win32\egg\openpyxl\workbook\workbook.py", line 281, in save
File "build\bdist.win32\egg\openpyxl\writer\excel.py", line 214, in save_workbook
File "build\bdist.win32\egg\openpyxl\writer\excel.py", line 197, in save
File "build\bdist.win32\egg\openpyxl\writer\excel.py", line 109, in write_data
File "build\bdist.win32\egg\openpyxl\writer\excel.py", line 134, in _write_worksheets
File "build\bdist.win32\egg\openpyxl\writer\worksheet.py", line 281, in write_worksheet
File "build\bdist.win32\egg\openpyxl\writer\worksheet.py", line 381, in write_worksheet_data
File "build\bdist.win32\egg\openpyxl\writer\worksheet.py", line 404, in write_cell
File "build\bdist.win32\egg\openpyxl\xml\functions.py", line 142, in start_tag
File "C:\Python27\lib\xml\sax\saxutils.py", line 159, in startElement
self._write(u' %s=%s' % (name, quoteattr(value)))
File "C:\Python27\lib\xml\sax\saxutils.py", line 104, in write
self.flush()
MemoryError
我认为导致此问题的代码如下,其中KeywordReport
是列表列表。
ws_keywords = wb.get_sheet_by_name("E_KWs")
for r, row in enumerate(KeywordReport, start=1):
for c, val in enumerate(row, start=1):
mycell = ws_keywords.cell(row=r, column=c)
mycell.value = val
mycell.style = Style(border=thin_border)
ws_keywords.column_dimensions['A'].width = 60.0
ws_keywords.column_dimensions['B'].width = 50.0
ws_keywords.column_dimensions['C'].width = 50.0
ws_keywords.column_dimensions['D'].width = 15.0
ws_keywords.column_dimensions['E'].width = 16.0
ws_keywords.column_dimensions['F'].width = 16.0
ws_keywords.column_dimensions['G'].width = 16.0
for ref in ['A1','B1','C1','D1','E1','F1','G1']:
cell = ws_keywords.cell(ref)
cell.style = Style(font=Font(bold=True),fill=PatternFill(patternType='solid', fgColor=Color('ffd156')), border=thin_border)
gc.collect()
del KeywordReport[:]
gc.collect()
print "start of save"
wb.save(attach_filepath)
gc.collect()
os.remove(temp_attach_filepath)
QCoreApplication.processEvents()
我查看了http://openpyxl.readthedocs.org/en/latest/optimized.html,但我认为我不能使用它来编写而不只是转储到新工作簿中,但我需要现有模板中的数据。
有没有办法解决这个问题?
【问题讨论】:
你确定吗?>>> a = [1,2,3] >>> del a[:] >>> a []
啊,你是对的,对不起。我会删除我的评论。
【参考方案1】:
500k 行应该不是太大的问题。但我想这也取决于你有多少工作表。你的系统有多少内存?
安装 lxml 会更快(就像在循环之外创建任何样式一样),但我不认为它会降低内存使用率。
如果您确实需要从现有工作簿中复制数据,您可能需要考虑使用单独的工作簿进行更改,这样可以减少读取和写入的内存使用。进一步讨论可能最好放在邮件列表中。
【讨论】:
系统内存是8GB,我觉得应该没问题。我正在尝试几种不同的方法,如果我能找到解决方案,我会提供反馈,如果没有,我会在邮件列表上发布。谢谢! 内存只是保存文件时的问题?文件中有很多文本吗?您能否提供一个您正在添加的数据类型的示例? 完全正确,仅在保存时。确实有很多文字,每个单元格都是30-50个字符左右的字符串。 如果这些是唯一的字符串,听起来您遇到了由格式中的“优化”引起的限制。请参阅 bitbucket.org/openpyxl/openpyxl/issue/196/… 以查看是否描述了这种情况。 啊,谢谢 - 这完美地描述了它。我现在已经用 xlsxwriter 重写了,一切似乎都在工作。感谢您的帮助。以上是关于MemoryError 使用 openpyxl 写入 500k+ 行的主要内容,如果未能解决你的问题,请参考以下文章