2017-11-30 1 views
1

다소 큰 .xlsx 파일이 있습니다. 19 열, 5185 행입니다. 파일을 열고 한 열의 모든 값을 읽고, 그 값에 몇 가지 작업을 수행 한 다음, 같은 통합 문서에 새 열을 만들고 수정 된 값을 쓰려고합니다. 따라서 동일한 파일에서 읽고 쓸 수 있어야합니다. 통합 문서가 너무 커서 때문에openpyxl의 읽기 전용 통합 문서의 열을 반복합니다.

def readExcel(doc): 
    wb = load_workbook(generalpath + exppath + doc) 
    ws = wb["Sheet1"] 

    # iterate through the columns to find the correct one 
    for col in ws.iter_cols(min_row=1, max_row=1): 
     for mycell in col: 
      if mycell.value == "PerceivedSound.RESP": 
       origCol = mycell.column 

    # get the column letter for the first empty column to output the new values 
    newCol = utils.get_column_letter(ws.max_column+1) 

    # iterate through the rows to get the value from the original column, 
    # do something to that value, and output it in the new column 
    for myrow in range(2, ws.max_row+1): 
     myrow = str(myrow) 
     # do some stuff to make the new value 
     cleanedResp = doStuff(ws[origCol + myrow].value) 
     ws[newCol + myrow] = cleanedResp 

    wb.save(doc) 

그러나, 파이썬은 행 3853 후 메모리 오류가 발생했습니다 :

내 원래의 코드는이했다. openpyxl 문서는 큰 통합 문서를 처리하기 위해 읽기 전용 모드 (https://openpyxl.readthedocs.io/en/latest/optimized.html)를 사용한다고합니다. 나는 그것을 사용하려고하고있다. AttributeError :

def readExcel(doc): 
    wb = load_workbook(generalpath + exppath + doc, read_only=True) 
    ws = wb["Sheet1"] 

    for col in ws.iter_cols(min_row=1, max_row=1): 
     #etc. 

파이썬이 오류가 발생합니다 : 그러나, 나는 READ_ONLY = 진정한 PARAM를 추가 할 때 열을 반복 할 수있는 방법은없는 것 같다 'ReadOnlyWorksheet'객체가 어떤 속성 'iter_cols 없다'

I가 위의 코드에서 마지막 줄을 변경할 경우 : 에서 :

for col in ws.columns: 

파이썬 같은 오류가 발생합니다 tributeError는 'ReadOnlyWorksheet'개체가 행에 대해 아무런 속성 '열'

순회 괜찮있다 (및 설명서 제가 위에 링크에 포함되어 있습니다) :

for col in ws.rows: 

(에러 없음)

This question은 AttritubeError에 대해 묻지 만 읽기 전용 모드를 제거하는 것이 해결책입니다. openpyxl은 읽기 전용 모드가 아닌 전체 통합 문서를 읽지 않기 때문에 저에게 적합하지 않습니다.

그래서 어떻게 대형 통합 문서의 열을 반복합니까?

아직이 문제가 발생하지 않았지만 한 번 열을 반복 할 수 있습니다. 통합 문서가 큰 경우 동일한 통합 문서를 읽고 쓰려면 어떻게해야합니까?

감사합니다.

답변

0

documentation에 따르면 ReadOnly 모드는 행 기반 읽기 만 지원합니다 (열 읽기는 구현되지 않음). 그러나 그것은 해결하기 어렵지 않다 :

wb2 = Workbook(write_only=True) 
ws2 = wb2.create_sheet() 

# find what column I need 
colcounter = 0 
for row in ws.rows: 
    for cell in row: 
     if cell.value == "PerceivedSound.RESP": 
      break 
     colcounter += 1 

    # cells are apparently linked to the parent workbook meta 
    # this will retain only values; you'll need custom 
    # row constructor if you want to retain more 

    row2 = [cell.value for cell in row] 
    ws2.append(row2) # preserve the first row in the new file 

break 

for row in ws.rows: 
    row2 = [cell.value for cell in row] 
    row2.append(doStuff(row2[colcounter])) 
    ws2.append(row2) # write a new row to the new wb 

wb2.save('newfile.xlsx') 
wb.close() 
wb2.close() 

# copy `newfile.xlsx` to `generalpath + exppath + doc` 
# Either using os.system,subprocess.popen, or shutil.copy2() 

같은 통합 문서에 쓸 수 없지만, 위의 그림과 같이 당신이 (쓰기 전용 모드에서) 새 통합 문서를 엽니 다 쓸 및 이전을 덮어 쓸 수 있습니다 OS 복사본을 사용하는 파일.

+0

다른 통합 문서간에 셀 개체를 전달할 수 없으므로 작동하지 않습니다. –

+0

같은 줄을 serialize 할 수 있습니다 :'row = [cell.value for cell in row]'? – cowbert

+0

확실히,하지만 이것은 서식, 주석 등을 잃어 버릴 것을 잊지 마십시오. –

0

워크 시트에 약 100,000 개의 셀만 있으면 메모리 문제가 없어야합니다. 당신은 아마 이것을 더 조사해야합니다.

iter_cols()은 기본 XML 파일을 지속적으로 매우 비효율적으로 다시 표시해야하기 때문에 읽기 전용 모드로 사용할 수 없습니다. 그러나 행을 에서 열로 변환하는 것이 상대적으로 쉽습니다. zip을 사용하십시오.

+0

나는 이것이 내게 거대한 워크 북처럼 보이지 않았기 때문에 처음에는 메모리 오류가 발생했을 때 놀랐다는 것에 동의한다. 그러나 그럼에도 불구하고 그랬다. 더 자세히 조사 할 것을 어떻게 제안합니까? – Jona

+0

파이썬 프로세스가 사용하고있는 메모리의 양과 통합 문서에있는 다른 메모리를 확인해야합니다. 파일이 없으면 훨씬 더 말할 수 없습니다. –

+0

위의 코드 전체를 게시했습니다. 보시다시피, 메모리 집약성 측면에서 많은 일이 일어나지 않습니다. "그 밖의 것은 통합 문서에 무엇이 있는가?"라는 말은 셀에 텍스트 (및 정수)가있는 통합 문서 일뿐입니다. 어떤 셀에도 수식, 참조, 거대한 텍스트가 없으며 워크 시트 내에서 계산되는 것이 없습니다. 참여자 데이터이기 때문에 파일을 공유 할 수 없지만 찾고자하는 방향으로 나를 가리킬 수 있다면 더 자세히 살펴볼 수 있습니다. – Jona

관련 문제