首页 > 代码库 > python标准库_csv

python标准库_csv

python标准库_csv

简介

所谓的csv(逗号分隔值Comma Separated Values)格式是最通用的用于电子表格和数据库的导入和导出格式。因为没有“csv标准”,所以格式被读写它的许多应用程序自由定义。缺乏标准也意味着不同应用程序在产生和使用数据时总是存在一些微小的差异。这些差异使得处理来自多种源的CSV文件时令人头疼。同时,分隔符和引用符的多样性,使得所有格式足够相近以至于编写一个能够有效操作这种数据,对程序员隐藏读写数据细节的独立模块成为可能。

函数

读文件

可以使用reader()创建一个对象从csv文件读取数据。这个阅读器可以用作一个迭代器,按顺序处理文件的行。

 

$ cat s_player_school_table.csv

c_school_id,c_hp_fixed,c_hp_factor,c_mana_fixed,c_mana_factor,c_ap_factor

0,150,20,140,15,1

1,90,20,140,15,1

2,180,20,151,15,1

3,229,20,177,15,4.4

4,208,20,177,15,6.7

5,208,20,177,15,6.7

 

$ cat read_csv.py

import csv

import sys

 

with open(sys.argv[1],‘r‘) as csv_file:

       csv_reader=csv.reader(csv_file)

       for row in csv_reader:

                print row

 

reader()的第一个参数是文本行的源。上例中是一个文件,也可以是任何可迭代的对象(如stringIO实例、list等等)。还可以指定其他可选参数,来控制如何解析输入数据。

$ cat read_from_list.py

import csv

 

csv_file=csv.reader([‘hello‘,‘signjing‘,‘goodnight‘])

for i in csv_file:

       print i

 

$ python read_from_list.py

[‘hello‘]

[‘signjing‘]

[‘good night‘]

 

读文件时,输入数据的每一行都会解析,并转换为一个字符串list

$ python read_csv.pys_player_school_table.csv

[‘c_school_id‘, ‘c_hp_fixed‘,‘c_hp_factor‘, ‘c_mana_fixed‘, ‘c_mana_factor‘, ‘c_ap_factor‘]

[‘0‘, ‘150‘, ‘20‘, ‘140‘, ‘15‘, ‘1‘]

[‘1‘, ‘90‘, ‘20‘, ‘140‘, ‘15‘, ‘1‘]

[‘2‘, ‘180‘, ‘20‘, ‘151‘, ‘15‘, ‘1‘]

[‘3‘, ‘229‘, ‘20‘, ‘177‘, ‘15‘, ‘4.4‘]

[‘4‘, ‘208‘, ‘20‘, ‘177‘, ‘15‘, ‘6.7‘]

[‘5‘, ‘208‘, ‘20‘, ‘177‘, ‘15‘, ‘6.7‘]

 

这个解析器会处理嵌在字符串中的换行符,正是这个原因,这里的行(row)并不一定等同于文件的一个输入行(line)。

 

$ cat s_player_school_table.csv

c_school_id,c_hp_fixed,c_hp_factor,c_mana_fixed,c_mana_factor,c_ap_factor

0,150,20,"abc

def",15,1

1,90,20,140,15,1

 

$ python read_csv.pys_player_school_table.csv

[‘c_school_id‘, ‘c_hp_fixed‘,‘c_hp_factor‘, ‘c_mana_fixed‘, ‘c_mana_factor‘, ‘c_ap_factor‘]

[‘0‘, ‘150‘, ‘20‘, ‘abc\ndef‘,‘15‘, ‘1‘]

[‘1‘, ‘90‘, ‘20‘, ‘140‘, ‘15‘, ‘1‘]

 

由解析器返回时,输入中带换行符的字段仍保留内部换行符。

 

阅读器对象

$ cat s_player_school_table.csv

c_school_id,c_hp_fixed,c_hp_factor,c_mana_fixed,c_mana_factor,c_ap_factor

0,150,20,"abc

def",15,1

1,90,20,140,15,1

 

$ cat attributes.py

import csv

 

with open(‘s_player_school_table.csv‘,‘r‘)as f:

       csv_file=csv.reader(f)

       for i in csv_file:

                print csv_file.dialect

                print i

                print csv_file.line_num

 

print

 

with open(‘s_player_school_table.csv‘,‘r‘)as f:

       csv_file=csv.DictReader(f)

       print csv_file.fieldnames

 

$ python attributes.py

<_csv.Dialect object at 0xb7c64ac0>

[‘c_school_id‘, ‘c_hp_fixed‘,‘c_hp_factor‘, ‘c_mana_fixed‘, ‘c_mana_factor‘, ‘c_ap_factor‘]

1

<_csv.Dialect object at 0xb7c64ac0>

[‘0‘, ‘150‘, ‘20‘, ‘abc\ndef‘, ‘15‘, ‘1‘]

3

<_csv.Dialect object at 0xb7c64ac0>

[‘1‘, ‘90‘, ‘20‘, ‘140‘, ‘15‘, ‘1‘]

4

 

[‘c_school_id‘, ‘c_hp_fixed‘,‘c_hp_factor‘, ‘c_mana_fixed‘, ‘c_mana_factor‘, ‘c_ap_factor‘]

 

写文件

写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

       print

 

writer=csv.writer(sys.stdout,dialect=dialect)

writer.writerow(

       (‘col1‘,1,‘10/01/2010‘,

       ‘special chars:"\‘ %s to parse‘ % dialect.delimiter)

       )

print

 

自动检测方言

要配置方言来解析一个输入文件,最好的办法就是提前知道正确的设置。对于方言参数未知的数据,可以用Sniffer类来做一个有根据地猜测。sniff()方法取一个输入数据样本和一个可选的参数(给出可能的定界字符)。

 

$ cat csv_dialect_sniffer.py

import csv

from StringIO import StringIO

import textwrap

 

csv.register_dialect(‘escaped‘,

                        escapechar=‘\\‘,

                        doublequote=False,

                        quoting=csv.QUOTE_NONE)

 

csv.register_dialect(‘singlequote‘,

                       quotechar="‘",

                        quoting=csv.QUOTE_ALL)

 

# generate sample data for all knowndialects

samples=[]

for name in sorted(csv.list_dialects()):

       buffer=StringIO()

       dialect=csv.get_dialect(name)

       write=csv.writer(buffer,dialect=dialect)

       write.writerow(

                (‘col1‘,1,‘10/01/2010‘,

                ‘special chars "\‘ %s toparse‘ % dialect.delimiter)

                )

       samples.append( (name,dialect,buffer.getvalue()) )

# guess the dialect for a given sample,andthen use the results to

# parse the data.

sniffer=csv.Sniffer()

for name,expected,sample in samples:

       print ‘Dialect:"%s"\n‘ % name

       dialect=sniffer.sniff(sample,delimiters=‘,\t‘)

       reader=csv.reader(StringIO(sample),dialect=dialect)

       print reader.next()

       print

 

sniff()会返回一个Dialect实例,其中包含用于解析数据的设置。这个结果并不总是尽善尽美,示例中的“escaped”方言可以说明这一点。

 

 

$ python csv_dialect_sniffer.py

Dialect:"escaped"

 

[‘col1‘, ‘1‘, ‘10/01/2010‘, ‘special chars\\"\‘ \\‘, ‘ to parse‘]

 

Dialect:"excel"

 

[‘col1‘, ‘1‘, ‘10/01/2010‘, ‘special chars"\‘ ‘, ‘ to parse"‘]

 

Dialect:"excel-tab"

 

[‘col1‘, ‘1‘, ‘10/01/2010‘, ‘special chars"\‘ ‘, ‘ to parse"‘]

 

Dialect:"singlequote"

 

[‘col1‘, ‘1‘, ‘10/01/2010‘, ‘special chars"\‘ , to parse‘]

 

获取方言

$ cat get_dialect.py

import csv

 

print csv.list_dialects()

list1=[‘excel‘,‘nothing‘]

print list1

 

for l in list1:

       try:

                print csv.get_dialect(l)

       except Exception,e:

                print e

 

$ python get_dialect.py

[‘excel-tab‘, ‘excel‘]

[‘excel‘, ‘nothing‘]

<_csv.Dialect object at 0xb7c88a60>

unknown dialect

删除方言

$ cat unregister_dialect.py

import csv

 

print csv.list_dialects()

list1=[‘excel‘,‘abc‘]

print list1

for l in list1:

       try:

                csv.unregister_dialect(‘excel‘)

                print csv.list_dialects()

       except Exception,e:

                print e

 

$ python unregister_dialect.py

[‘excel-tab‘, ‘excel‘]

[‘excel‘, ‘abc‘]

[‘excel-tab‘]

unknown dialect

 

字段长度限制

$ cat field_size_limit.py

import csv

 

with open(‘s_player_school_table.csv‘,‘r‘)as f:

       csv_file=csv.reader(f)

       for c in csv_file:

                print csv.field_size_limit()

 

print

 

with open(‘s_player_school_table.csv‘,‘r‘)as f:

       limit=100

       csv_file=csv.reader(f)

       for c in csv_file:

                limit+=1

                print csv.field_size_limit(limit)

 

$ python field_size_limit.py

131072

131072

131072

 

131072

101

102

由此可见,如果设置了限制,则函数先返回当前的长度限制,然后在使用新的limit覆盖原有的limit值。

使用字段名

除了处理数据序列,csv模块还包括一些类,可以将行作为字典来处理,从而可以对字段命名。DictReaderDictWriter类将行转换为字典而不是列表。字典的键可以传入,也可以由输入的第一行推导得出(如果行包含首部)。

 

$ cat csv_dictreader.py

import csv

import sys

 

with open(sys.argv[1],‘r‘) as f:

       reader=csv.DictReader(f)

       for row in reader:

                print row

 

$ cat temp.csv

"a","b","c"

1,"a","08/01/07"

2,"b","08/02/07"

3,"c","08/03/07"

 

$ python csv_dictreader.py temp.csv

{‘a‘: ‘1‘, ‘c‘: ‘08/01/07‘, ‘b‘: ‘a‘}

{‘a‘: ‘2‘, ‘c‘: ‘08/02/07‘, ‘b‘: ‘b‘}

{‘a‘: ‘3‘, ‘c‘: ‘08/03/07‘, ‘b‘: ‘c‘}

 

基于字典的阅读器和书写器会实现为基于序列的类的包装器,它们使用相同的方法和参数。阅读器api唯一的差别是:行将作为字典返回,而不是作为列表或元组。

 

必须为DictWriter提供一个字段名列表,使它知道如何在输出中确定列的顺序。

 

$ python csv_dictwriter.py temp.csv

Title 1,Title 2,Title 3

1,a,08/01/07

2,b,08/02/07

3,c,08/03/07

 

 

$ cat temp.csv

Title 1,Title 2,Title 3

1,a,08/01/07

2,b,08/02/07

3,c,08/03/07

 

$ cat csv_dictwriter.py

import csv

import sys

 

with open(sys.argv[1],‘w‘) 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,

                                ‘Title2‘:chr(ord(‘a‘)+i),

                                ‘Title3‘:‘08/%02d/07‘ %(i+1),

                                })

 

print open(sys.argv[1],‘r‘).read()

 

字段名并不会自动写至文件,所以需要在写其他数据之前显式写出。

$ 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()

[signjing@localhost share_db]$ catcsv_dictwriter.py

import csv

import sys

 

with open(sys.argv[1],‘w‘) 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,

                                ‘Title2‘:chr(ord(‘a‘)+i),

                                ‘Title 3‘:‘08/%02d/07‘ %(i+1),

                                })

 

print open(sys.argv[1],‘r‘).read()

生词本

1. encounter [in?kaunt?]

vt. 不期而遇;遭遇;对抗;

n. 相遇,碰见;遭遇战;对决,冲突;

vi. 碰见,尤指不期而遇

 

2. acronym [??kr??n?m]

n. 首字母缩略词

 

3. standardized [?st?nd??daizd]

adj. 标准的,定型的;

v. 使合乎规格,使标准化( standardize的过去式和过去分词 )

 

4. numeric [nju:?merik]

adj. 数字的;数值的

 

5. assigned [?‘sa?nd]

n.[计][修](已)赋值[分配];[计]指定的,赋值的

adj.指定的,赋值的

v.分配( assign的过去式和过去分词 );指派;指定;(作为说明或原因)提出

 

6. Proposal [pr??p?uz?l]

n. 提议;建议;求婚;〈美〉投标

 

7. spreadsheet [?spred??i:t]

n. 电子制表软件,电子数据表

 

8. subtle [?s?tl]

adj. 微妙的;敏感的;狡猾的;巧妙的

 

9. annoying [??n????]

adj. 讨厌的;恼人的;

v. 骚扰(annoy的ing形式)

 

10. quoting [kw?ut??]

v. 引用,援引( quote的现在分词 );报价;引述;为(股票、黄金或外汇)报价

 

11. overall [??uv?r?:l]

adj. 全部的;全体的;一切在内的;综合的;

adv. 全面地;总地;总的说来;

n. 工装裤;罩衫;〈英〉(军官的)紧身军裤

 

12. efficiently [??f???ntl?]

adv. 效率高地;有效地

 

13. manipulate [m??nipjuleit]

vt. 操作,处理;巧妙地控制;操纵;[医] 推拿,调整

 

14. tabular [?t?bj?l?]

adj. 表格的;按表格计算的;平坦的;平板(状)的

 

15. preferred [pri?f?:d]

adj. 首选的;

v. 提出(请求、控诉等)( prefer的过去式和过去分词 );提升;建议;选择某事物(而不选择他事物)

 

16. precise [pri?sais]

adj. 清晰的;精确的;正规的;精密

 

17. Accordingly [??k?:di?li]

adv. 因此,于是;依据;照着,相应地

 

18. According [??k?:di?]

adv. 依照;

v. 给予( accord的现在分词 );使和谐一致;使符合;使适合adj. 相符的,和谐的,相应的

 

19. dialect [?dai?lekt]

n. 方言,土语;语调;[语]语支;专业用语

 

20. iterate [??t??re?t]

vt. 重复;反复申明

 

21. protocol [?pr??t??k?:l, -?k??l, -?k?l]

n. 礼仪;(外交条约的)草案;(数据传递的)协议;科学实验报告(或计划);

vt. 把……写入议定书,在议定书中拟定(或颁布);

vi. 拟定议定书,拟定草案

 

22. optional [??p??nl]

adj. 可选择的;随意的,任意的;非强制的;选修科目

 

23. Previously [?pri:vj?sl?]

adv. 事先;以前;仓促;“previous”的派生

 

24. carriage return

n. 回车

 

25. consequence [?k?nsikw?ns]

n. 结果,成果;[逻]结论;重要性;推论

 

26. responsible [ri?sp?ns?bl]

adj. 尽责的;承担责任;负有责任的;懂道理的

 

27. immutable [??mju:t?b?l]

adj. 不可改变的

 

28. underlying [??nd??laii?]

adj. 潜在的,含蓄的;基础的;表面下的,下层的;[法]优先的;

v. 优先于(underlie的ing形式);构成……的基础(或起因),引起

 

29. so-called [?s???k?:ld]

adj. 所谓的,号称的

 

30. vary [?v??ri]

vi. 变化;不同,偏离;[生]变异;

vt. 使不同;使多样化;[音乐]变奏

 

31. reflecting [r??flekt??]

adj. 反射的,引起反射的;沉思的;

v. 反射(光、热、声或影像)( reflect的现在分词 );考虑;反照;表达