2015-01-06 49 views
2

我有一個腳本,它使用openpyxl打開模板xlsx文件,然後跨越六個工作表中的每一個,在腳本中添加一些前面生成的列表中的數據並更改單元格的格式。MemoryError使用openpyxl寫入500k +行

我遇到的問題是,在一張紙上,我需要寫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但我不認爲我可以用這只是沒有傾銷到一個新的工作簿寫的,但我需要在我現有的模板中的數據。

有沒有辦法解決這個問題?

+0

你確定嗎? '>>> a = [1,2,3] >>> del a [:] >>> a []' – samg86

+0

啊,你是對的,對不起。我會刪除我的評論。 –

回答

2

500k行應該不是太大的問題。但我想這也取決於你有多少工作表。你有多少內存在系統上?

安裝lxml會更快(因爲會在循環之外創建任何樣式),但我不希望它將內存使用降低太多。

如果您確實需要從現有工作簿中複製數據,則可能需要考慮使用單獨的工作簿進行更改,這樣可以減少內存使用量,包括讀取和寫入。進一步的討論可能是最好的郵件列表。

+0

系統內存爲8GB,所以應該沒問題。我正在嘗試一些不同的方式來做這件事,如果我能找到一個解決方案並在郵件列表上發佈,如果沒有的話,我會做出反饋。謝謝! – samg86

+0

保存文件時內存只是一個問題?你的文件中有很多文字嗎?你能提供一個你正在添加的數據類型的例子嗎? –

+0

完全正確,只有在保存時。確實有很多文字,每個單元格都是大約30-50個字符的字符串。 – samg86