csv.DictWriter로 헤더 행을 작성하는 방법은 무엇입니까?


114

csv.DictReader개체가 있고 CSV 파일로 작성하고 싶다고 가정 합니다. 어떻게 할 수 있습니까?

다음 과 같이 데이터 행을 쓸 수 있다는 것을 알고 있습니다 .

dr = csv.DictReader(open(f), delimiter='\t')
# process my dr object
# ...
# write out object
output = csv.DictWriter(open(f2, 'w'), delimiter='\t')
for item in dr:
    output.writerow(item)

그러나 필드 이름을 어떻게 포함시킬 수 있습니까?

답변:


149

편집 :
2.7 / 3.2에는 새로운 writeheader()방법이 있습니다. 또한 John Machin의 답변은 헤더 행을 작성하는 더 간단한 방법을 제공합니다. 이제 2.7 / 3.2에서 사용 가능한 방법
을 사용하는 간단한 예 writeheader():

from collections import OrderedDict
ordered_fieldnames = OrderedDict([('field1',None),('field2',None)])
with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=ordered_fieldnames)
    dw.writeheader()
    # continue on to write data

DictWriter를 인스턴스화하려면 fieldnames 인수가 필요합니다.
에서 문서 :

fieldnames 매개 변수는 writerow () 메소드에 전달 된 사전의 값이 csvfile에 기록되는 순서를 식별합니다.

다른 말로하면 : Python dicts는 본질적으로 순서가 지정되지 않았기 때문에 Fieldnames 인수가 필요합니다.
다음은 헤더와 데이터를 파일에 쓰는 방법의 예입니다.
참고 : with명령문은 2.6에서 추가되었습니다. 2.5를 사용하는 경우 :from __future__ import with_statement

with open(infile,'rb') as fin:
    dr = csv.DictReader(fin, delimiter='\t')

# dr.fieldnames contains values from first row of `f`.
with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames)
    headers = {} 
    for n in dw.fieldnames:
        headers[n] = n
    dw.writerow(headers)
    for row in dr:
        dw.writerow(row)

@FM이 주석에서 언급했듯이 헤더 쓰기를 한 줄로 압축 할 수 있습니다. 예 :

with open(outfile,'wb') as fou:
    dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames)
    dw.writerow(dict((fn,fn) for fn in dr.fieldnames))
    for row in dr:
        dw.writerow(row)

12
+1 헤더를 작성하는 또 다른 방법 : dw.writerow( dict((f,f) for f in dr.fieldnames) ).
FMc 2010-06-05

2
@Adam : 더 짧은 한 줄짜리에 대해서는 내 대답을 참조하십시오.
John Machin

2
@John : 답변에 +1; 단순히 "기본 작성자 인스턴스"를 사용하는 것이 "노력적인 ID 매핑"보다 확실히 바람직합니다.
mechanical_meat

1
@endolith : 피드백에 감사드립니다. 그 부분을 답변의 맨 위로 옮겼습니다.
mechanical_meat

1
dictReader도 사용하고 있기 때문에 dw = csv.DictWriter(fou, delimiter='\t', fieldnames=dr.fieldnames). 이렇게하면 필드가 변경 되어도 dictWriter를 조정할 필요가 없습니다.
Spencer Rathbun 2012

29

몇 가지 옵션 :

(1) csv.DictWriter가 목록으로 다시 변환하여 csv.writer 인스턴스로 전달할 수 있도록 필드 이름에서 ID 매핑 (즉, 아무것도하지 않음) dict를 열심히 만듭니다.

(2) 문서에 "기본 writer인스턴스"가 언급 되어 있으므로 사용하십시오 (마지막의 예).

dw.writer.writerow(dw.fieldnames)

(3) csv.Dictwriter 오버 헤드를 피하고 csv.writer로 직접 수행

데이터 쓰기 :

w.writerow([d[k] for k in fieldnames])

또는

w.writerow([d.get(k, restval) for k in fieldnames])

extrasaction"기능" 대신에 직접 코딩하는 것을 선호합니다. 이렇게하면 첫 번째 추가 키뿐 아니라 키와 값으로 모든 "추가"를보고 할 수 있습니다. DictWriter의 실제 성가신 점은 각 딕셔너리가 빌드 될 때 키를 직접 확인했다면 extrasaction = 'ignore'를 사용하는 것을 기억해야한다는 것입니다.

wrong_fields = [k for k in rowdict if k not in self.fieldnames]

============

>>> f = open('csvtest.csv', 'wb')
>>> import csv
>>> fns = 'foo bar zot'.split()
>>> dw = csv.DictWriter(f, fns, restval='Huh?')
# dw.writefieldnames(fns) -- no such animal
>>> dw.writerow(fns) # no such luck, it can't imagine what to do with a list
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\python26\lib\csv.py", line 144, in writerow
    return self.writer.writerow(self._dict_to_list(rowdict))
  File "C:\python26\lib\csv.py", line 141, in _dict_to_list
    return [rowdict.get(key, self.restval) for key in self.fieldnames]
AttributeError: 'list' object has no attribute 'get'
>>> dir(dw)
['__doc__', '__init__', '__module__', '_dict_to_list', 'extrasaction', 'fieldnam
es', 'restval', 'writer', 'writerow', 'writerows']
# eureka
>>> dw.writer.writerow(dw.fieldnames)
>>> dw.writerow({'foo':'oof'})
>>> f.close()
>>> open('csvtest.csv', 'rb').read()
'foo,bar,zot\r\noof,Huh?,Huh?\r\n'
>>>

현재 Python 3.6에서는 extrasaction기능이 더 잘 구현 된 것 같습니다. 이제 wrong_fields = rowdict.keys() - self.fieldnames so it's effectively a 설정된 작업입니다.
martineau 2017

나는이 답변을 'Avoid DictWriter'코멘트에 찬성하고 있습니다-나는 그것을 사용하는 것의 이점을 보지 못했고, 데이터를 구조화하고 csv.writer를 사용하는 것이 더 빠른 것 같습니다
neophytte

8

이를 수행하는 또 다른 방법은 출력에 행을 추가하기 전에 다음 행을 추가하는 것입니다.

output.writerow(dict(zip(dr.fieldnames, dr.fieldnames)))

zip은 동일한 값을 포함하는 이중 목록을 반환합니다. 이 목록은 사전을 시작하는 데 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.