- CSV是纯文本文件,Excel是二进制文件
- CSV文件的读写
所谓CSV文件,就是“逗号分隔值文件”的简称,通常来说,这个文件类似于一个表格的结构,每一行都有相同的列,并且一般使用逗号隔开。一个典型的CSV文件类似于下面的形式:
PassengerId, Pclass, Name, Sex, Age, SibSp, Parch, Ticket, Fare, Cabin, Embarked
892,3, "Kelly, Mr. James", male,34.5,0,0,330911,7.8292, , Q
893,3, "Wilkes, Mrs. James (Ellen Needs)", female,47,1,0,363272,7, , S
894,2, "Myles, Mr. Thomas Francis", male,62,0,0,240276,9.6875, , Q
895,3, "Wirz, Mr. Albert", male,27,0,0,315154,8.6625, , S
其中第一行是表头,其余的行是数据,如果有包含空格的字符串,那么一般会使用双引号括起来。
2.1 读取CSV文件
# ! /usr/bin/python
# -*- coding: utf-8-*-
from __future__ import print_function
import csv
with open('/Users/jilu/Downloads/test.csv', 'r') as fr:
rows = csv.reader(fr)
for row in rows:
print(row)
运行结果:
['PassengerId', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp', 'Parch', 'Ticket',
'Fare', 'Cabin', 'Embarked']
['892', '3', 'Kelly, Mr. James', 'male', '34.5', '0', '0', '330911', '7.8292',
'', 'Q']
['893', '3', 'Wilkes, Mrs. James (Ellen Needs)', 'female', '47', '1', '0',
'363272', '7', '', 'S']
['894', '2', 'Myles, Mr. Thomas Francis', 'male', '62', '0', '0', '240276',
'9.6875', '', 'Q']
['895', '3', 'Wirz, Mr. Albert', 'male', '27', '0', '0', '315154', '8.6625', '', 'S']
['896', '3', 'Hirvonen, Mrs. Alexander (Helga E Lindqvist)', 'female', '22',
'1', '1', '3101298', '12.2875', '', 'S']
2.2 创建CSV文件
with open('./csv_tutorial.csv', 'a') as fw:
writer = csv.writer(fw)
writer.writerow(["c1", 'c2', 'c3'])
for x in range(10):
writer.writerow([x, chr(ord('a') + x), 'abc'])
创建结果如下:
c1, c2, c3
0, a, abc
1, b, abc
2, c, abc
3, d, abc
4, e, abc
5, f, abc
6, g, abc
7, h, abc
8, i, abc
9, j, abc
细心的读者可能会发现,这里的字符串没有用双引号括起来,这只是因为默认的csv. writer()并不会自动为字符串增加双引号[插图],若想要增加双引号,可以使用下面的代码:
writer = csv.writer(fw, quoting=csv.QUOTE_NONNUMERIC)
代替原来代码中的:
writer = csv.writer(fw)
结果如下:
"c1", "c2", "c3"
0, "a", "abc"
1, "b", "abc"
2, "c", "abc"
3, "d", "abc"
4, "e", "abc"
5, "f", "abc"
6, "g", "abc"
7, "h", "abc"
8, "i", "abc"
9, "j", "abc"
2.3 处理方言
虽然CSV格式的文件是以逗号作为分隔符号的文件,但实际上并没有一个严格的定义要求其必须用逗号。比如Hadoop中的表文件,如果以纯文本的形式输出,那么默认的分隔符就是“\x01”。你也可能会见到使用管道符“|”作为分割符的CSV文件,我们统一称这种CSV为CSV的方言。
以上文创建的CSV文件csv_tutorial.csv为例,现在将逗号改为管道符,并且另存为csv_tutorial.pipe.csv,其中的内容如下:
"c1"|"c2"|"c3"
0|"a"|"abc"
1|"b"|"abc"
2|"c"|"abc"
3|"d"|"abc"
...
想要读取这个文件可以参考下面的代码:
csv.register_dialect('pipes', delimiter='|')
with open('/Users/jilu/Downloads/csv_tutorial.pipe.csv', 'r') as fr:
rows = csv.reader(fr, dialect='pipes')
for row in rows:
print(row)
如果使用csv中的register_dialect()函数注册一个新的方言,命名为“pipes”,并且将“|”作为分割符,那么上面程序的执行结果将为:
['c1', 'c2', 'c3']
['0', 'a', 'abc']
['1', 'b', 'abc']
['2', 'c', 'abc']
['3', 'd', 'abc']
...
可以看到,这确实可以读取我们自定义的CSV方言。创建自定义方言的过程与读取的过程一样,只需要在csv.writer()函数中传入一个dialect='pipes’参数即可,在此就不赘述了。
2.4 将读取的结果转换成字典
部分读者可能还没有意识到,如果CSV文件拥有大量的栏,那么想要确认某一个数据在第几栏将是一件多么麻烦的事情。所幸,CSV模块提供了一种以字典结构返回数据的方式,即使用CSV模块中的DictReader(),参考下面的代码:
with open('/Users/jilu/Downloads/test.csv', 'r') as fr:
rows = csv.DictReader(fr)
for row in rows:
print(row)
其运行的结果如下:
{'Fare': '7.8292', 'Name': 'Kelly, Mr. James', 'Embarked': 'Q', 'Age': '34.5',
'Parch': '0', 'Pclass': '3', 'Sex': 'male', 'SibSp': '0', 'PassengerId':
'892', 'Ticket': '330911', 'Cabin': ''}
{'Fare': '7', 'Name': 'Wilkes, Mrs. James (Ellen Needs)', 'Embarked': 'S',
'Age': '47', 'Parch': '0', 'Pclass': '3', 'Sex': 'female', 'SibSp': '1',
'PassengerId': '893', 'Ticket': '363272', 'Cabin': ''}
{'Fare': '9.6875', 'Name': 'Myles, Mr. Thomas Francis', 'Embarked': 'Q',
'Age': '62', 'Parch': '0', 'Pclass': '2', 'Sex': 'male', 'SibSp': '0',
'PassengerId': '894', 'Ticket': '240276', 'Cabin': ''}
程序会自动将每一行数据组织成一个字典,这样我们就无需关心第几列是什么数据了,只要使用字典的键就能获取我们想要的信息,这是极为方便的。