2010-06-05 3 views
87

csv.DictReader 개체가 있다고 가정하고이를 CSV 파일로 작성하고 싶습니다. 어떻게해야합니까?csv.DictWriter로 헤더 행을 쓰는 방법은 무엇입니까?

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) 

하지만 어떻게 내가 fieldName에 포함될 수 있습니다

은 내가 데이터 같은의 행을 쓸 수 있는지 알아?

답변

110

편집 :
2.7/3.2에는 a new writeheader() method이 있습니다. 또한 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은 fieldName에 인수가 필요합니다.
the documentation에서 :되는 writerow에 전달 딕셔너리의 값은

fieldName에 파라미터 식별 순서() 메소드는 csvfile 기록된다.

다른 말로 표현 : 파이썬 사전에 본질적으로 순서가 지정되지 않았기 때문에 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) 
+10

+1 헤더를 쓰는 또 다른 방법은 다음과 같습니다.'dw.writerow (dr.fieldnames에서 fict에 대한 dict (f, f))'. – FMc

+2

@ Adam : 짧은 한 줄짜리는 내 대답을 참조하십시오. –

+2

@ John : 대답에 +1; 간단히 "근원적 인 작가의 실례 (instance)"를 이용하는 것은 "힘든 신원 매핑"보다 바람직하다. – bernie

23

몇 가지 옵션 :

(1) csv.DictWriter가 목록으로 다시 변환하여 csv.writer 인스턴스로 전달할 수 있도록 필드 이름에서 신원 매핑 (즉, 아무것도하지 않음)을 지정합니다.

(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의 진짜 불쾌한 점은 각 dict이 만들어 질 때 열쇠를 직접 확인했다면 extrasaction = 'ignore'를 사용하는 것을 잊지 말아야한다는 것입니다. 그렇지 않으면 SLOWLY로 이동합니다 (fieldnames는 목록입니다).

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' 
>>> 
+0

현재 파이썬 3.6에서'extrasaction' 기능이 더 잘 구현 된 것 같습니다. 그것은 이제'wrong_fields = rowdict.keys() - self.fieldnames입니다. 그래서 효과적으로'set' 연산입니다. – martineau

9

당신의 출력 라인을 추가하기 전에 추가하는 것이 작업을 수행하는 또 다른 방법은, 다음 줄

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

우편 번호가 후퇴합니다. n 같은 값을 포함하는 doublet의리스트. 이 목록은 사전을 시작하는 데 사용될 수 있습니다.

관련 문제