2014-02-19 2 views
6

Я написал сценарий, который должен прочитать много файлов excel из папки (около 10 000). Этот скрипт загружает файл excel (некоторые из них имеют более 2000 строк) и читает один столбец для подсчета количества строк (проверка материала). Если количество строк не равно заданному числу, оно записывает предупреждение в журнал.Ошибка памяти с использованием openpyxl и больших данных превосходит

Проблема возникает, когда скрипт читает более 1000 файлов excel. Это тогда, когда он выдает ошибку памяти, и я не знаю, где может быть проблема. Ранее скрипт считывал два файла csv с 14 000 строк и сохранял их в списке. Эти списки содержат идентификатор для файла excel и его соответствующее количество строк. Если это число строк не равно количеству строк файла excel, оно записывает предупреждение. Может быть, проблема с чтением этих списков?

Я использую openpyxl для загрузки книг, мне нужно закрыть их, прежде чем открывать следующий?

Это мой код:

# -*- coding: utf-8 -*- 

import os 
from openpyxl import Workbook 
import glob 
import time 
import csv 
from time import gmtime,strftime 
from openpyxl import load_workbook 

folder = '' 
conditions = 0 
a = 0 
flight_error = 0 
condition_error = 0 
typical_flight_error = 0 
SP_error = 0 


cond_numbers = [] 
with open('Conditions.csv','rb') as csv_name:   # Abre el fichero csv donde estarán las equivalencias 
    csv_read = csv.reader(csv_name,delimiter='\t') 

    for reads in csv_read: 
     cond_numbers.append(reads) 

flight_TF = [] 
with open('vuelo-TF.csv','rb') as vuelo_TF: 
    csv_read = csv.reader(vuelo_TF,delimiter=';') 

    for reads in csv_read: 
     flight_TF.append(reads) 


excel_files = glob.glob('*.xlsx') 

for excel in excel_files: 
    print "Leyendo excel: "+excel 

    wb = load_workbook(excel) 
    ws = wb.get_sheet_by_name('Control System') 
    flight = ws.cell('A7').value 
    typical_flight = ws.cell('B7').value 
    a = 0 

    for row in range(6,ws.get_highest_row()): 
     conditions = conditions + 1 


     value_flight = int(ws.cell(row=row,column=0).value) 
     value_TF = ws.cell(row=row,column=1).value 
     value_SP = int(ws.cell(row=row,column=4).value) 

     if value_flight == '': 
      break 

     if value_flight != flight: 
      flight_error = 1    # Si no todos los flight numbers dentro del vuelo son iguales 

     if value_TF != typical_flight: 
      typical_flight_error = 2   # Si no todos los typical flight dentro del vuelo son iguales 

     if value_SP != 100: 
      SP_error = 1 



    for cond in cond_numbers: 
     if int(flight) == int(cond[0]): 
      conds = int(cond[1]) 
      if conds != int(conditions): 
       condition_error = 1   # Si el número de condiciones no se corresponde con el esperado 

    for vuelo_TF in flight_TF: 
     if int(vuelo_TF[0]) == int(flight): 
      TF = vuelo_TF[1] 
      if typical_flight != TF: 
       typical_flight_error = 1  # Si el vuelo no coincide con el respectivo typical flight 

    if flight_error == 1: 
     today = datetime.datetime.today() 
     time = today.strftime(" %Y-%m-%d %H.%M.%S") 
     log = open('log.txt','aw') 
     message = time+': Los flight numbers del vuelo '+str(flight)+' no coinciden.\n' 
     log.write(message) 
     log.close() 
     flight_error = 0 

    if condition_error == 1: 
     today = datetime.datetime.today() 
     time = today.strftime(" %Y-%m-%d %H.%M.%S") 
     log = open('log.txt','aw') 
     message = time+': El número de condiciones del vuelo '+str(flight)+' no coincide. Condiciones esperadas: '+str(int(conds))+'. Condiciones obtenidas: '+str(int(conditions))+'.\n' 
     log.write(message) 
     log.close() 
     condition_error = 0 

    if typical_flight_error == 1: 
     today = datetime.datetime.today() 
     time = today.strftime(" %Y-%m-%d %H.%M.%S") 
     log = open('log.txt','aw') 
     message = time+': El vuelo '+str(flight)+' no coincide con el typical flight. Typical flight respectivo: '+TF+'. Typical flight obtenido: '+typical_flight+'.\n' 
     log.write(message) 
     log.close() 
     typical_flight_error = 0 

    if typical_flight_error == 2: 
     today = datetime.datetime.today() 
     time = today.strftime(" %Y-%m-%d %H.%M.%S") 
     log = open('log.txt','aw') 
     message = time+': Los typical flight del vuelo '+str(flight)+' no son todos iguales.\n' 
     log.write(message) 
     log.close() 
     typical_flight_error = 0 

    if SP_error == 1: 
     today = datetime.datetime.today() 
     time = today.strftime(" %Y-%m-%d %H.%M.%S") 
     log = open('log.txt','aw') 
     message = time+': Hay algún Step Percentage del vuelo '+str(flight)+' menor que 100.\n' 
     log.write(message) 
     log.close() 
     SP_error = 0 

    conditions = 0 

Условного заявление конца предназначено для проверки и записи журналов предупреждений.

Я использую Windows XP с 8 ГБ оперативной памяти и Intel xeon w3505 (два ядра, 2,53 ГГц).

ответ

9

По умолчанию реализация openpyxl будет хранить все доступные ячейки в памяти. Я предлагаю вам использовать Оптимизированный читатель (ссылку - https://openpyxl.readthedocs.org/en/latest/optimized.html) вместо

В коде: -

wb = load_workbook(file_path, use_iterators = True) 

При загрузке книг проходит use_iterators = True. Затем доступ к листу и клетке, как:

for row in sheet.iter_rows(): 
    for cell in row: 
     cell_text = cell.value 

Это позволит уменьшить объем памяти до 5-10%

UPDATE: В версии 2.4.0 use_iterators = True опции удалена. В новых версиях openpyxl.writer.write_only.WriteOnlyWorksheet вводится для сбрасывания больших объемов данных.

from openpyxl import Workbook 
wb = Workbook(write_only=True) 
ws = wb.create_sheet() 

# now we'll fill it with 100 rows x 200 columns 
for irow in range(100): 
    ws.append(['%d' % i for i in range(200)]) 

# save the file 
wb.save('new_big_file.xlsx') 

Не проверен нижеследующий код, просто скопированный по приведенной выше ссылке.

С благодарностью @SdaliM за информацию.

+1

Этот вариант, кажется, не существует больше (openpyxl 2.4.1). Указанная ссылка не упоминает такой вариант. Может, ты знаешь замену? – SdaliM

0

С недавних версиях openpyxl приходится загружать и читать огромный источник книги с read_only=True аргументом, и создать/написать огромную книгу назначения с write_only=True режиме:

https://openpyxl.readthedocs.io/en/latest/optimized.html

Смежные вопросы