Python 如何使用csv.DictWriter写入标题行?

Python 如何使用csv.DictWriter写入标题行?,python,csv,Python,Csv,假设我有一个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) 但是

假设我有一个
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中,有一个。此外,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 dict本身就是无序的。
下面是如何将标题和数据写入文件的示例。
注:
with
语句添加在2.6中。如果使用2.5:
from\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu语句导入

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) 费力地从字段名中创建一个标识映射(即不做任何事情)dict,以便csv.DictWriter可以将其转换回列表并将其传递给csv.writer实例

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

(3) 避免csv.writer开销,自己使用csv.writer完成

写入数据:

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

我宁愿自己编写代码,而不是
extracation
“功能”;这样,您就可以报告所有带有键和值的“附加”,而不仅仅是第一个附加键。DictWriter真正令人讨厌的是,如果您在构建每个dict时自己验证了密钥,您需要记住使用extrasaction='ignore',否则它将缓慢运行(FieldName是一个列表)重复检查:

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'
>>>
f=open('csvtest.csv','wb') >>>导入csv >>>fns='foo-bar-zot'.split() >>>dw=csv.DictWriter(f,fns,restval='Huh?')) #dw.writefieldnames(fns)——没有这样的动物 >>>dw.writerow(fns)#没有这样的运气,它无法想象如何处理列表 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 writerow中的文件“C:\python26\lib\csv.py”,第144行 返回self.writer.writerow(self.\u dict\u to\u list(rowdict)) 文件“C:\python26\lib\csv.py”,第141行,在目录列表中 return[rowdict.get(key,self.restval)用于输入self.fieldnames] AttributeError:“list”对象没有属性“get” >>>处长(数据仓库) [“文档”、“初始化”、“模块”、“目录列表”、“外泄”、“字段名称” es',restval',writer',writerow',writerows'] #尤里卡 >>>dw.writer.writerow(dw.fieldnames) >>>writerow({'foo':'oof'}) >>>f.关闭() >>>打开('csvtest.csv','rb')。读取() 'foo,bar,zot\r\noof,嗯?,嗯?\r\n' >>>
另一种方法是在输出中添加行之前添加以下行:

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

zip将返回包含相同值的doublet列表。此列表可用于启动字典。

+1另一种编写标题的方法:
dw.writerow(dict((f,f)表示dr.fieldnames中的f))
@Adam:有关较短的一行,请参阅我的答案。@John:+1表示您的答案;简单地利用“底层编写者实例”当然比“费力的身份映射”更可取。@endolith:感谢您的反馈。将该部分移到答案的顶部。由于您也在使用dictReader,因此添加带有
dw=csv.DictWriter(fou,delimiter='\t',fieldnames=dr.fieldnames)
的字段很容易。这样,如果字段发生更改,则不需要调整dictWriter。目前在Python 3.6中,
extraction
功能似乎实现得更好。现在它是
错误的\u fields=rowdict.keys()-self.fieldnames,因此它实际上是一个
set`操作。我投票支持这个答案,支持“避免DictWriter”注释-我没有看到使用它的任何优势,似乎可以更快地构建数据和使用csv.writer
>>> 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)))