写文件
写csv文件与读csv文件同样容易。可以使用writer()创建一个对象来写数据,然后使用writerow()迭代处理文本行进行打印。
$ cat write_a_csv.py
import sys
import csv
with open(sys.argv[1],'w') as csv_file:
csv_writer=csv.writer(csv_file)
csv_writer.writerow(('a','b','c'))
for i in range(3):
csv_writer.writerow( (i+1,
chr(ord('a')+i),
'08/%02d/07' %(i+1),
)
)
print open(sys.argv[1],'r').read()
执行结果:
a,b,c
1,a,08/01/07
2,b,08/02/07
3,c,08/03/07
$ cat temp.csv
a,b,c
1,a,08/01/07
2,b,08/02/07
3,c,08/03/07
引导:
对于书写器,默认的引号行为有所不同。要加引号,需要将quoting参数设置为另外某种引号模式。
writer=csv.writer(f,quoting=csv.QUOTE_NONNUMERIC)
这样,QUOTE_NONNUMERIC会在所有包含非数值内容的列周围加引号。
$ Python write_a_csv.py temp.csv
"a","b","c"
1,"a","08/01/07"
2,"b","08/02/07"
3,"c","08/03/07"
$ cat temp.csv
"a","b","c"
1,"a","08/01/07"
2,"b","08/02/07"
3,"c","08/03/07"
$ cat write_a_csv.py
import sys
import csv
with open(sys.argv[1],'w') as csv_file:
csv_writer=csv.writer(csv_file,quoting=csv.QUOTE_NONNUMERIC)
csv_writer.writerow(('a','b','c'))
for i in range(3):
csv_writer.writerow( (i+1,
chr(ord('a')+i),
'08/%02d/07'%(i+1),
)
)
print open(sys.argv[1],'r').read()
有4种不同的引号选项,在csv模块中定义为四个变量:
QUOTE_ALL不论类型是什么,对所有字段都加引号。
QUOTE_MINIMAL对包含特殊字符的字段加引号(所谓特殊字符是指,对于一个用相同方言和选项配置的解析器,可能会造成混淆的字符)。这是默认选项。
QUOTE_NONNUMERIC对所有非整数或浮点数的字段加引号。在阅读器中使用时,不加引号的输入字段会转换为浮点数。
QUOTE_NONE输出中所有内容都不加引号。在阅读器中使用时,引号字符包含在字段值中(正常情况下,它们会处理为定界符并去除)。
方言
逗号分隔值文件没有明确定义的标准,所以解析器必须灵活。这种灵活性意味着可以用很多参数来控制csv如何解析或写数据。并不是将各个参数单独传入阅读器和书写器,可以把它们成组在一起构成一个方言(dialect)对象。
dialect类可以按名注册,这样csv模块的调用者就不需要提前知道参数设置。可以用list_dialects()获取完整的已注册方言列表。
$ cat csv_list_dialects.py
import csv
print csv.list_dialects()
$ python csv_list_dialects.py
['excel-tab', 'excel']
这个标准库包含两个方言:excel和excel-tabs。excel方言用于处理采用Microsoft Excel默认导出格式的数据,也可以处理openoffice或neooffice。
创建方言
可以不使用逗号来分隔字段,输入文件使用了竖线(|):
$ cat testdata.pipes
"Title 1"|"Title2"|"Title 3"
1|"first line
second line"|08/18/07
$ cat csv_dialect.py
import csv
csv.register_dialect('pipes',delimiter='|')
print csv.list_dialects()
with open('testdata.pipes','r') as f:
reader=csv.reader(f,dialect='pipes')
for row in reader:
print row
$ python csv_dialect.py testdata.pipes
['excel-tab', 'excel', 'pipes']
['Title 1', 'Title 2', 'Title 3']
['1', 'first line\nsecond line','08/18/07']
使用“pipes”方言,可以像逗号定界文件一样读取文件。
方言参数
方言指定了解析或写一个数据文件时使用的所有记号(token)。
csv方言参数
属性
默认值
含义
delimiter
,
字段分隔符(一个字符)
doublequote
True
这个标志控制quotechar实例是否成对
escapechar
None
这个字符用来指示一个转义序列
lineterminator
\r\n
书写器使用这个字符结束一行
quotechar
“
这个字符串用来包围包含特殊值的字段(一个字符)
quoting
QUOTE_MINIMAL
控制前面介绍的引号行为
skipinitialspace
False
忽略字段定界符后面的空白符
strict
False
当设置为True时,错误的csv输入将弹出异常Error。
执行结果:
$ python csv_dialect_variations.py
Dialect:"escaped"
delimiter = ',' skipinitialspace = 0
doublequote = 0 quoting = QUOTE_NONE
quotechar = '"' lineterminator = '\r\n'
escapechar = '\\'
Dialect:"excel"
delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_MINIMAL
quotechar = '"' lineterminator = '\r\n'
escapechar = None
Dialect:"excel-tab"
delimiter = '\t' skipinitialspace = 0
doublequote= 1 quoting = QUOTE_MINIMAL
quotechar = '"' lineterminator = '\r\n'
escapechar = None
Dialect:"singlequote"
delimiter = ',' skipinitialspace = 0
doublequote = 1 quoting = QUOTE_ALL
quotechar = "'" lineterminator = '\r\n'
escapechar = None
'col1','1','10/01/2010','specialchars:"'' , to parse'
源文件:
$ cat csv_dialect_variations.py
import csv
import sys
csv.register_dialect('escaped',
escapechar='\\',
doublequote=False,
quoting=csv.QUOTE_NONE,
)
csv.register_dialect('singlequote',
quotechar="'",
quoting=csv.QUOTE_ALL,
)
quoting_modes=dict( (getattr(csv,n),n)
for n in dir(csv)
ifn.startswith('QUOTE_')
)
for name in sorted(csv.list_dialects()):
print 'Dialect:"%s"\n' % name
dialect=csv.get_dialect(name)
print ' delimiter = %-6r skipinitialspace = %r' %(
dialect.delimiter,dialect.skipinitialspace)
print ' doublequote = %-6r quoting = %s' %(
dialect.doublequote,quoting_modes[dialect.quoting])
print ' quotechar = %-6r lineterminator = %r' %(
dialect.quotechar,dialect.lineterminator)
print ' escapechar = %-6r' % dialect.escapechar
writer=csv.writer(sys.stdout,dialect=dialect)
writer.writerow(
('col1',1,'10/01/2010',
'special chars:"\' %s to parse' % dialect.delimiter)
)