如何用csv.DictWriter编写标题行?

假设我有一个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的顺序。

换句话说:Fieldnames参数是必需的,因为Python字典本身是无序的。
下面是如何将标题和数据写入文件的示例。
注意:2.6中增加with语句。 如果使用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实例。

(2)文档中提到“底层编写器实例”…所以只是使用它(最后的例子)。

 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 “function”,我宁愿自己编码; 这样你可以用键和值报告所有的“额外”,而不仅仅是第一个额外的键。 DictWriter真正的麻烦在于,如果您在构build每个字典时都自己validation了密钥,则需要记住使用extrasaction ='ignore',否则将慢慢地(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' >>> 

另一种方法是在添加行之前添加行,如下所示:

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

该zip将返回一个包含相同值的doublet列表。 这个列表可以用来启动一个字典。