作用:读写逗号分隔值文件。
Python版本:2.3及以后版本
可以用csv模块处理从电子表格和数据库导出的数据,并写入采用字段和记录格式的文本 文件,这种格式通常称为逗号分隔值(comma-separated value, CSV)格式,因为常用逗号来 分隔记录中的字段。
读文件
可以使用reader创建一个对象从CSV文件读取数据。这个阅读器可以用作一个迭代器,按顺序处理文件中的行例如:
import csv
with open("testdata.csv", 'rt') as f:
reader = csv.reader(f)
for row in reader:
print row
reader()的第一个参数是文本行的源。在这个例子中,这是一个文件,不过也可以是任何可迭代的对象(如StringIO实例、list等等)。还可以指定其他可选参数,来控制如何解析输入数据。
"Title 1","Title 2","Title 3"
1,"a",08/18/07
2,"b",08/19/07
3,"c",08/20/07
读文件时,输入数据的每一行都会解析,并转换为一个字符串list。
['Title 1', 'Title 2', 'Title 3']
['1', 'a', '08/18/07']
['2', 'b', '08/19/07']
['3', 'c', '08/20/07']
[Finished in 0.1s]
这个解析器会处理嵌在行字符串中的换行符,正是因为这个原因,这里的“行”(row)并 不一定等同于文件的一个输入“行”(line)。
写文件
写CSV文件与读CSV文件同样容易。可以使用writer创建一个对象来写数据,然后使用writerow迭代处理文本行进行打印。
import csv
with open("testout.csv", 'wt') as f:
writer = csv.writer(f)
writer.writerow( ('Title 1', 'Title 2', 'Title 3') )
for i in range(3):
writer.writerow( (i+1,
chr(ord('a') + i),
'08/%02d/07' % (i+1),
)
)
print open("testout.csv", 'rt').read()
这里的输出与阅读器示例中使用的导出数据看上去不完全相同。
Title 1,Title 2,Title 3
1,a,08/01/07
2,b,08/02/07
3,c,08/03/07
[Finished in 0.1s]
引号
对于书写器,默认的引号行为有所不同,所以前例中第2列和第3列没有加引号。要加引号,需要将quoting参数设置为另外某种引号模式。
writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
在这里,QUOTE_NONNUMERIC会在所有包含非数值内容的列周围加引号
import csv
with open("testout_quoted.csv", 'wt') as f:
writer = csv.writer(f, quoting=csv.QUOTE_NONNUMERIC)
writer.writerow( ('Title 1', 'Title 2', 'Title 3') )
for i in range(3):
writer.writerow( (i+1, chr(ord('a') + i), '08/%02d/07' % (i+1)) )
print open("testout_quoted.csv", 'rt').read()
运行结果:
"Title 1","Title 2","Title 3"
1,"a","08/01/07"
2,"b","08/02/07"
3,"c","08/03/07"
[Finished in 0.1s]
有4种不同的引号选项,在csv模块中定义为4个常量。
- QUOTE_ALL
不论类型是什么,对所有字段都加引号。
- QUOTE_MINIMAL
对包含特殊字符的字段加引号(所谓特殊字符是指,对于一个用相同方言和选项配置的解析器,可能会造成混淆的字符)。这是默认选项
- QUOTE_NO_MERIC
对所有非整数或浮点数的字段加引号。在阅读器中使用时,不加引号的输入字段会转换为浮点数。
- QUOTE_NONE
输出中所有内容都不加引号。在阅读器中使用时,引号字符包含在字段值中(正常情况下,它们会处理为定界符并去除)。
方言
逗号分隔值文件没有明确定义的标准,所以解析器必须很灵活。这种灵活性意味着可以用很多参数来控制CSV如何解析或写数据。并不是将各个参数单独传入阅读器和书写器,可以把它们成组在一起构成一个方言dialect对象。
Dialect类可以按名注册,这样CSV槙块的调用者就不需要提前知道参数设置。可以用list_ dialects。获取完整的已注册方言列表。
import csv
print csv.list_dialects ()
这个标准库包括两个方言:excel和excel-tabs。excel方言用于处理采用Microsoft Excel默认导出格式的数据,也可以处理OpenOffice或NeoOffice。
['excel-tab', 'excel']
[Finished in 0.1s]
创建方言
可以不使用逗号来分隔宇段,输入文件使用了竖线(|),如下所示:
"Title 1"|"Title 2"|"Title 3"
1|"first line
second line"|08/18/07
可以使用适当的定界符注册一个新的方言。
import csv
csv.register_dialect('pipes', delimiter='|')
with open('testdata.pipes', 'r') as f:
reader = csv.reader(f, dialect='pipes')
for row in reader:
print row
使用“pipes”方言,可以像逗号定界文件一样读取文件。
['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line', '08/18/07']
[Finished in 0.1s]
其他参数可以查看帮助进行。
字段名
除了处理数据序列,CSV模块还包括一些类,可以将行作为字典来处理,从而可以对字段命名。DictReader和DictWriter类将行转换为字典而不是列表。字典的键可以传入,也可以由输入的第一行推导得出(如果行包含首部)。
import csv
with open("testdata.csv", 'rt') as f:
reader = csv.DictReader(f)
for row in reader:
print row
基于字典的阅读器和书写器会实现为基于序列的类的包装器,它们使用相同的方法和参数。阅读器API中惟一的差别是:行将作为字典返回,而不是作为列表或元组。
{'Title 1': '1', 'Title 3': '08/18/07', 'Title 2': 'a'}
{'Title 1': '2', 'Title 3': '08/19/07', 'Title 2': 'b'}
{'Title 1': '3', 'Title 3': '08/20/07', 'Title 2': 'c'}
[Finished in 0.1s]
必须为DictWriter提供一个字段名列表,使它知道如何在输出中确定列的顺序.
import csv
with open("testout.csv", 'wt') as f:
fieldnames = ('Title 1', 'Title 2', 'Title 3')
headers = dict( (n,n) for n in fieldnames )
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writerow(headers)
for i in range(3):
writer.writerow({ 'Title 1':i+1,
'Title 2':chr(ord('a') + i),
'Title 3':'08/%02d/07' % (i+1),
})
print open("testout.csv", 'rt').read()
字段名并不自动写至文件,所以需要在写其他数据之前显式写出。
Title 1,Title 2,Title 3
1,a,08/01/07
2,b,08/02/07
3,c,08/03/07
[Finished in 0.1s]