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)
그러나 필드 이름을 어떻게 포함시킬 수 있습니까?
답변
편집 :
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)
답변
몇 가지 옵션 :
(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'
>>>
답변
이를 수행하는 또 다른 방법은 출력에 행을 추가하기 전에 다음 행을 추가하는 것입니다.
output.writerow(dict(zip(dr.fieldnames, dr.fieldnames)))
zip은 동일한 값을 포함하는 이중 목록을 반환합니다. 이 목록은 사전을 시작하는 데 사용할 수 있습니다.