我真的很喜欢Python的csv模块。但是我确实希望它记录得更好。
dictwriter允许您通过将每行定义为python dict。
这是文档中的示例:
import csv
with open('names.csv', 'w', newline='') as csvfile:
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})
a,它忽略了我认为的(如果不是 )标准用例,我一直都遇到的用例从字面上看,但更像:
import csv
data = [('Baked', 'Beans'),
('Lovely', 'Spam'),
('Wonderful', 'Spam'),
]
with open('names.csv', 'w', newline='') as csvfile:
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for datum in data:
writer.writerow({'first_name': datum[0],
'last_name': datum[1]})
当然:
- 源通常不会是元组的列表,而是对象的迭代器,我正在倾倒它们的某些属性。
- 我将使用一个**多**更长的字面名称列表。
这提高了重复相同字段名称列表的幽灵,绝对不是DRY,并且在我调整要转储到CSV的字段列表时,高度不受欢迎且难以维护。
但是我没有发现任何文档可以解决。因此,刚刚插入并进行了测试后,值得放在文件中(就在这里和现在)。
问题
简而言之,问题是csv.DictWriter
要求知道fieldnames
(并且writer.writeheader()
需要知道它们),但是它们是在循环内的字典中指定的。 fieldnames
甚至不是csv.DictWriter
的可选论点,而writer
是poorly documented。
解决方案
该解决方案在两个经验上确定(由于缺乏文档)事实:
-
csv.DictWriter
接受fieldnames=None
-
writer
如果返回具有可以在创建后设置的fieldnames
属性。
机智,这很漂亮:
import csv
data = [('Baked', 'Beans'),
('Lovely', 'Spam'),
('Wonderful', 'Spam'),
]
with open('names.csv', 'w', newline='') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=None)
for i, datum in enumerate(data):
row = {'first_name': datum[0],
'last_name': datum[1]}
if i == 0:
writer.fieldnames = row.keys()
writer.writeheader()
writer.writerow()
现在未指定行键。 CSV文件接收其标题行。
曾经发现的一个简单的范式,我正在迅速倾倒描述对象的CSV文件,主要用于测试和学习目的。这意味着我可以在原位使用row
定义,添加行和更改的行等,而无需在两个地方更改它们,并且我从dictwriter及其简单的语法中受益。