07-DictReader和DictWriter CSV对象
16.1.5 DictReader和DictWriter CSV对象
对于包含列标题行的CSV文件,通常使用 DictReader 和 DictWriter 对象,而不是使用 reader 和 writer 对象,因为这样会更方便。
reader 和 writer 对象通过使用列表对CSV文件的行进行读写。 DictReader 和 DictWriter CSV对象实现相同的功能,但使用的是字典,且它们使用CSV文件的第一行作为这些字典的键。
进入异步社区本书对应页面,下载 exampleWithHeader.csv 文件。这个文件和example.csv一样,只是第一行是列标题Timestamp、Fruit和Quantity。
要读取该文件,请在交互式环境中输入以下内容:
>>> import csv
>>> exampleFile = open('exampleWithHeader.csv')
>>> exampleDictReader = csv.DictReader(exampleFile)
>>> for row in exampleDictReader:
... print(row['Timestamp'], row['Fruit'], row['Quantity'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98
在这个循环中, DictReader 对象将 row 设置为一个字典对象,该对象的键值来自第一行中的列标题。(从技术上来说,它把 row 设置为一个 OrderedDict 对象,你可以用和字典一样的方式使用它,它们之间的区别不在本书的范围之内。)使用 DictReader 对象意味着你不需要编写额外的代码来跳过第一行的列标题信息,因为 DictReader 对象会帮你做这件事。
如果你试图对 example.csv 使用 DictReader 对象,而 example.csv 在第一行中没有列标题信息,那么 DictReader 对象将使用 '4/5/2015 13:34' 、 'Apples' 和 '73' 作为字典键。为了避免这种情况,你可以在 DictReader() 函数中加入第二个参数,其中包含了预置的列标题名:
>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleDictReader = csv.DictReader(exampleFile, ['time', 'name', 'amount'])
>>> for row in exampleDictReader:
... print(row['time'], row['name'], row['amount'])
...
4/5/2015 13:34 Apples 73
4/5/2015 3:41 Cherries 85
4/6/2015 12:46 Pears 14
4/8/2015 8:59 Oranges 52
4/10/2015 2:07 Apples 152
4/10/2015 18:10 Bananas 23
4/10/2015 2:40 Strawberries 98
因为 example.csv 的第一行中每一列的标题都没有任何文字,所以我们创建了自己的列标题: 'time' 、 'name' 和 'amount' 。
DictWriter 对象使用字典来创建CSV文件。
>>> import csv
>>> outputFile = open('output.csv', 'w', newline='')
>>> outputDictWriter = csv.DictWriter(outputFile, ['Name', 'Pet', 'Phone'])
>>> outputDictWriter.writeheader()
>>> outputDictWriter.writerow({'Name': 'Alice', 'Pet': 'cat', 'Phone': '555- 1234'})
20
>>> outputDictWriter.writerow({'Name': 'Bob', 'Phone': '555-9999'})
15
>>> outputDictWriter.writerow({'Phone': '555-5555', 'Name': 'Carol', 'Pet': 'dog'})
20
>>> outputFile.close()
如果你想让文件包含一个标题行,那就调用 writeheader() 来写入这一行;否则,跳过调用 writeheader() 来省略文件中的标题行。然后,调用 writerow() 方法来写入CSV文件的每一行,并传入一个字典,该字典使用标题作为键,并包含要写入文件的数据。
这段代码创建的output.csv文件看起来是这样的:
Name,Pet,Phone
Alice,cat,555-1234
Bob,,555-9999
Carol,dog,555-5555
注意,传入 writerow() 的字典中的键-值对的顺序并不重要:它们是按照给 DictWriter() 的键的顺序写的。例如,在第4行,即使你把 Phone 的键和值放在 Name 和 Pet 的键和值之前,在输出结果中,电话号码仍然最后出现。
另外,请注意,任何缺失的键在CSV文件中都会是空的,例如, {'Name': 'Bob','Phone':'555-999999'} 中没有'Pet'。