使用Python的CSV DICDWRITER倾倒数据
#python #csv

我真的很喜欢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]})

当然:

  1. 源通常不会是元组的列表,而是对象的迭代器,我正在倾倒它们的某些属性。
  2. 我将使用一个**多**更长的字面名称列表。

这提高了重复相同字段名称列表的幽灵,绝对不是DRY,并且在我调整要转储到CSV的字段列表时,高度不受欢迎且难以维护。

但是我没有发现任何文档可以解决。因此,刚刚插入并进行了测试后,值得放在文件中(就在这里和现在)。

问题

简而言之,问题是csv.DictWriter要求知道fieldnames(并且writer.writeheader()需要知道它们),但是它们是在循环内的字典中指定的。 fieldnames甚至不是csv.DictWriter的可选论点,而writerpoorly documented

解决方案

该解决方案在两个经验上确定(由于缺乏文档)事实:

  1. csv.DictWriter接受fieldnames=None
  2. 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及其简单的语法中受益。