2014-09-11 3 views
1

위치를 편집하여 CSV 파일에 행을 추가하려면 어떻게해야합니까? 나는 원래, (의사)을 임시 파일에 기록한 다음, 교체의 패턴을 피하려는 : 중간 복사본을 만들지 않고 csvfile에 행 추가

add_records_to_csv(newdata, infile, tmpfile) 
delete(infile) 
rename(tmpfile, infile) 

는 여기에 실제 기능입니다. 기존의이 기록으로 새로운 행이 동일한 구조를 가지고 있다면

def add_records_to_csv(dic, csvfile): 
    """ Append a dictionary to a CSV file. 
     Adapted from http://pymotw.com/2/csv/ 
    """ 
    f_old = open(csvfile, 'rb')       # <-- 
    csv_old = csv.DictReader(f_old)      # <-- 

    fpath, fname = os.path.split(csvfile)    # <-- 
    csvfile_new = os.path.join(fpath, 'new_' + fname) # <-- 
    print(csvfile_new)         # <-- 
    f = open(csvfile_new, 'wb')       # <-- 

    try: 
     fieldnames = sorted(set(dic.keys() + csv_old.fieldnames)) 
     writer = csv.DictWriter(f, fieldnames=fieldnames) 
     headers = dict((n,n) for n in fieldnames) 
     writer.writerow(headers) 
     for row in csv_old: 
      writer.writerow(row) 
     writer.writerow(dic) 
    finally: 
     f_old.close() 
     f.close() 
    return csvfile_new 
+0

파일 (바이트)의 크기는 어느 정도입니까? 몇 줄의 원본과 예상 된 결과를 게시 할 수 있습니까? – wwii

+0

@wwii, [여기] (https://github.com/maphew/Speed-test/tree/master/stats/GEOMATT)는 csv의 일부입니다. 완전히 대표적인 세트는 아니지만 다른 열이있는 것들이 있습니다. Dan이 덕분에 개별적으로 처리해야한다는 것을 깨달았습니다. –

답변

1

은 다음이 작동합니다 : - 라인 "# <"나는 제거 할 및/또는 더 간단 무언가로 응축 무엇

import csv 

def append_record_to_csv(dic, csvfile): 
    with open(csvfile, 'rb') as f: 
     # discover order of field names in header row 
     fieldnames = next(csv.reader(f)) 
    with open(csvfile, 'ab') as f: 
     # assumes that dic contains only fieldnames in csv file 
     dwriter = csv.DictWriter(f, fieldnames=fieldnames) 
     dwriter.writerow(dic) 

반면에 새로운 행을 기존 행과 다른 구조로 작성하면 csv 파일의 형식이 잘못되었을 수 있습니다. csv 파일에 새 열을 추가하려면 모든 행을 편집해야합니다. 이 접근 방식의 성능은 매우 좋지 않으며 대형 CSV 파일에서 눈에 띄게됩니다.

+1

좋은 방법입니다. 문제는 @ mattwilkie의 코드에 따르면 새로운 행을 추가 할 때 새로운 필드를 추가하기를 원한다는 것입니다 :'fieldnames = sorted (set (dic.keys() + csv_old.fieldnames))' –

+0

@DanLenski : 충분합니다. 필드 이름이 동일하다고 가정하는 코드에 주석을 추가했습니다. 나는이 가정이 정당하다고 생각한다. OP의 현재 접근 방식은 새로운 표제가 도입되면 이전의 행을 새로운 CSV 파일로 다시 쓰는 것을 잘못 할 것이기 때문이다. –

+1

[DictWriter의 기본 동작은 사전에서 누락 된 필드를 공백으로 대체하는 것입니다] (https://docs.python.org/2/library/csv.html#csv.DictWriter); OP는 그것을 인식하지 않고이 동작에 의존하고있을 수 있습니다. 반면에 사전에 * extra * 필드가 있으면 예외가 발생합니다. 종류의 혼동. –

3

이것은 일반적으로 가능하지 않습니다. 여기 당신의 코드에서, 이유입니다 : 나에게

fieldnames = sorted(set(dic.keys() + csv_old.fieldnames)) 

,이 적어도 어떤 경우에는 새 행이 이전 행에없는 열이 포함되어 있다고 말한다. 이와 같이 행을 추가하면 끝에 새 행을 추가하는 것 외에도 파일의 헤더 (첫 번째 행)를 업데이트해야합니다. 열 이름을 영문자 순서로 지정해야하는 경우 열의 순서를 유지하려면 다른 모든 행의 필드를 다시 정렬해야 할 수 있습니다.

파일의 첫 번째 줄을 편집해야 할 수도 있으므로 마지막 줄에 새 줄을 추가하고 중간에 모든 줄을 편집하는 것 외에도이 작업을 내부에서 수행하는 합리적인 방법이 없습니다 .

내 제안은 프로그램에 헤더를 편집 할 필요가 없으며 단순히 새로운 행을 추가 할 수 있도록하기 위해 포함해야 할 모든 필드/열을 미리 확인하는 것이 좋습니다.

+0

아, 맞습니다. 입력 파일을 동일한 열을 가진 세트로 그룹화하거나 각 csvfile을 읽고 단일 화합 된 파일로 출력하는 방법을 찾아야합니다. 이것은 내가 깨달은 것보다 더 커졌습니다! –

+1

자신의 관계형 데이터베이스 시스템을 발명 할 위험이있는 것 같습니다 .-). 예기치 않은 "키와 값의 무작위 조합"을 실제로 저장해야하는 경우 MongoDB와 같은 문서 데이터베이스 또는 [JSON] (https://en.wikipedia.org/wiki/JSON)을 지원하는 실제 RDBMS는 다음과 같이 지원합니다. PostgreSQL은 좋은 해결책입니다. 이 모든 데이터는이 데이터로 수행 할 작업과 수행 할 작업의 양에 따라 다릅니다. –

+0

내 궁극적 인 목표는 85 개의 개별 csv 파일을 거의 동일하지는 않지만 거의 동일한 열 (일반 세트가 있음)과 병합하여 Excel로 분석 할 수있는 단일 테이블로 만드는 것입니다. 다음은 샘플입니다. https://github.com/maphew/Speed-test/tree/master/stats/GEOMATT –

관련 문제