所谓的CSV(逗号分隔值)格式是电子表格和数据库最常用的导入和导出格式。在尝试以标准化方式描述格式之前,CSV格式使用了很多年 RFC 4180。缺乏明确定义的标准意味着不同应用程序生成和使用的数据通常存在细微差别。这些差异会使从多个来源处理CSV文件变得很烦人。尽管如此,虽然分隔符和引用字符各不相同,但整体格式足够相似,以至于可以编写单个模块,该模块可以有效地操纵这些数据,隐藏从程序员读取和写入数据的细节。

csv模块实现了以CSV格式读取和写入表格数据的类。它允许程序员说“以Excel首选格式编写此数据”或“从Excel生成的此文件中读取数据”,而不知道Excel使用的CSV格式的精确细节。程序员还可以描述其他应用程序理解的CSV格式或定义自己的专用CSV格式。

csv模块readerwriter对象读取和写入序列。程序员还可以使用DictReaderDictWriter类以字典形式读写数据。

也可以看看

PEP 305 – CSV文件API
Python Enhancement Proposal提出了对Python的这一补充。

模块内容

csv模块定义了以下功能:

csv.readercsvfiledialect =’excel’** fmtparams 
返回一个读取器对象,它将迭代给定csvfile中的行。 csvfile可以是任何支持迭代器协议的对象,并在每次__next__()调用其方法时返回一个字符串- 文件对象和列表对象都是合适的。如果csvfile是文件对象,则应该打开它newline=''。[1]可以给出 一个可选的 方言参数,用于定义特定于CSV方言的一组参数。它可以是类的子类的实例,也可以是函数Dialect返回的字符串之一 list_dialects()。其他可选的fmtparams可以给出关键字参数来覆盖当前方言中的各个格式参数。有关方言和格式参数的完整详细信息,请参阅方言和格式参数一节。

从csv文件读取的每一行都作为字符串列表返回。除非QUOTE_NONNUMERIC指定了format选项(在这种情况下,未加引号的字段将转换为浮点数),否则不会执行自动数据类型转换。

一个简短的用法示例:

>>>
>>> import csv
>>> with open('eggs.csv', newline='') as csvfile:
...     spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
...     for row in spamreader:
...         print(', '.join(row))
Spam, Spam, Spam, Spam, Spam, Baked Beans
Spam, Lovely Spam, Wonderful Spam

 

csv.writercsvfiledialect =’excel’** fmtparams 
返回一个writer对象,负责将用户的数据转换为给定的类文件对象上的分隔字符串。 csvfile可以是带有write()方法的任何对象 。如果csvfile是文件对象,则应使用newline='' [1]打开它 。 可以给出可选的方言参数,该参数用于定义特定于CSV方言的一组参数。它可以是类的子类的实例,也可以是 函数Dialect返回的字符串之一list_dialects()。可以给出其他可选的fmtparams关键字参数来覆盖当前方言中的各个格式参数。有关方言和格式参数的完整详细信息,请参阅部分方言和格式参数。为了使与实现DB API的模块接口尽可能简单,将值None写为空字符串。虽然这不是可逆转换,但它可以更容易地将SQL NULL数据值转储到CSV文件,而无需预处理从cursor.fetch*调用返回的数据。所有其他非字符串数据str()在写入之前都会进行字符串化。

一个简短的用法示例:

import csv
with open('eggs.csv', 'w', newline='') as csvfile:
    spamwriter = csv.writer(csvfile, delimiter=' ',
                            quotechar='|', quoting=csv.QUOTE_MINIMAL)
    spamwriter.writerow(['Spam'] * 5 + ['Baked Beans'])
    spamwriter.writerow(['Spam', 'Lovely Spam', 'Wonderful Spam'])

 

csv.register_dialectname [dialect [** fmtparams 
方言名称联系起来。 name必须是一个字符串。方言可以通过传递子类Dialect,或通过fmtparams关键字参数或两者来指定,并使用关键字参数覆盖方言的参数。有关方言和格式参数的完整详细信息,请参阅方言和格式参数一节。
csv.unregister_dialect名字
从方言注册表中删除与名称关联的方言。Error如果name不是已注册的方言名称,则引发An 。
csv.get_dialect名字
返回与姓名相关的方言。Error如果name不是已注册的方言名称,则引发 An 。此函数返回不可变的Dialect
csv.list_dialects
返回所有已注册方言的名称。
csv.field_size_limitnew_limit 
返回解析器允许的当前最大字段大小。如果给出new_limit,则这将成为新限制。

csv模块定义了以下类:

class csv.DictReaderffieldnames = Nonerestkey = Nonerestval = Nonedialect =’excel’* args** kwds 
创建一个像常规阅读器一样操作的对象,但将每行中的信息映射到OrderedDict 其键由可选的fieldnames参数给出。

字段名的参数是一个序列。如果省略fieldnames,则文件f的第一行中的值将用作字段名。无论字段名如何确定,有序字典都保留其原始顺序。

如果一行包含的字段多于字段名,则将剩余数据放入一个列表中,并使用restkey指定的字段(默认为None)进行存储。如果非空行的字段少于字段名,则缺少的值将填入None

所有其他可选或关键字参数都传递给基础 reader实例。

在版本3.6中更改:返回的行现在是类型OrderedDict

一个简短的用法示例:

>>>
>>> import csv
>>> with open('names.csv', newline='') as csvfile:
...     reader = csv.DictReader(csvfile)
...     for row in reader:
...         print(row['first_name'], row['last_name'])
...
Eric Idle
John Cleese

>>> print(row)
OrderedDict([('first_name', 'John'), ('last_name', 'Cleese')])

 

class csv.DictWriterffieldnamesrestval =”extrasaction =’raise’dialect =’excel’* args** kwds 
创建一个像常规编写器一样操作的对象,但将字典映射到输出行。的字段名的参数是一个sequence标识,其中在传递给字典值的顺序按键的writerow()方法被写入到文件 ˚F。如果字典缺少字段名中的键,则可选的restval参数指定要写入的值。如果传递给方法的字典包含在字段名中找不到的键 ,则可选的extrasaction参数指示要采取的操作。如果设置为, 则引发默认值a 。如果设置为writerow()'raise'ValueError'ignore',字典中的额外值将被忽略。任何其他可选或关键字参数都将传递给基础 writer实例。

请注意,与DictReader类不同,类的fieldnames参数DictWriter不是可选的。

一个简短的用法示例:

import csv

with open('names.csv', 'w', newline='') as csvfile:
    fieldnames = ['first_name', 'last_name']
    writer = csv.DictWriter(csvfile, fieldnames=fieldnames)

    writer.writeheader()
    writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
    writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
    writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})

 

csv.Dialect
Dialect类是依赖于主要用于它的属性,这是用来定义一个特定的参数的容器类 readerwriter实例。
csv.excel
excel类定义的Excel生成CSV文件的通常的性质。它以方言名称注册'excel'
csv.excel_tab
所述excel_tab类定义Excel生成的制表符分隔的文件的通常的性质。它以方言名称注册'excel-tab'
csv.unix_dialect
unix_dialect类定义在UNIX系统上,即,使用生成的CSV文件的通常性质'\n'如线路终端机和引用的所有字段。它以方言名称注册'unix'

版本3.2中的新功能。

csv.Sniffer
Sniffer类用来推断一个CSV文件的格式。

Sniffer类提供了两个方法:

sniff样本分隔符=无
分析给定的样本并返回Dialect反映找到的参数的子类。如果给出了可选的delimiters参数,则将其解释为包含可能的有效分隔符的字符串。
has_header样本
分析示例文本(假定为CSV格式), True如果第一行显示为一系列列标题,则返回。

使用示例Sniffer

with open('example.csv', newline='') as csvfile:
    dialect = csv.Sniffer().sniff(csvfile.read(1024))
    csvfile.seek(0)
    reader = csv.reader(csvfile, dialect)
    # ... process CSV file contents here ...

 

csv模块定义以下常量:

csv.QUOTE_ALL
指示writer对象引用所有字段。
csv.QUOTE_MINIMAL
指示writer对象只引用那些包含特殊字符,如字段分隔符quotechar或任何字符 lineterminator
csv.QUOTE_NONNUMERIC
指示writer对象引用所有非数字字段。

指示读者将所有非引用字段转换为float类型。

csv.QUOTE_NONE
指示writer对象永远不引用字段。当输出数据中出现当前 分隔符时,它前面是当前的escapechar 字符。如果未设置escapechar,则Error在遇到任何需要转义的字符时,编写器将引发。

指示reader不对引号字符执行任何特殊处理。

csv模块定义了以下异常:

异常csv.Error
检测到错误时由任何功能引发。

方言和格式参数

为了便于指定输入和输出记录的格式,将特定格式参数组合在一起成为方言。方言是Dialect具有一组特定方法和单个validate()方法的类的子类。在创建reader或 writer对象时,程序员可以指定类的字符串或子Dialect类作为dialect参数。除了方言参数之外,或者代替方言参数,程序员还可以指定单独的格式化参数,这些参数与下面为Dialect类定义的属性具有相同的名称。

方言支持以下属性:

Dialect.delimiter
用于分隔字段的单字符字符串。它默认为','
Dialect.doublequote
控制如何引用字段中出现的quotechar实例。什么时候True,角色加倍。当 False时,escapechar作为前缀quotechar。它默认为True

在输出时,如果双引号False没有escapechar设置, Error如果需要进行上调quotechar是在现场发现的。

Dialect.escapechar
由作家使用的一个字符串转换为逃避分隔符,如果报价 被设置为QUOTE_NONEquotechar如果双引号False。在阅读时,escapechar从以下字符中删除任何特殊含义。默认为None,禁用转义。
Dialect.lineterminator
用于终止由生成的行的字符串writer。它默认为'\r\n'

注意

reader是硬编码的,可以识别'\r'或者'\n'作为行尾,并忽略行终止符。此行为将来可能会发生变化。

Dialect.quotechar
一个单字符的字符串,用于引用包含特殊字符的字段,例如分隔符quotechar,或者包含换行符。它默认为'"'
Dialect.quoting
控制何时应由作者生成引号并由读者识别。它可以采用任何QUOTE_*常量(请参阅模块内容一节 )并默认为QUOTE_MINIMAL
Dialect.skipinitialspace
何时True,忽略分隔符后面的空格。默认是False
Dialect.strict
何时TrueError在错误的CSV输入上引发异常。默认是False

读者对象

Reader对象(函数DictReader返回的实例和对象 reader())具有以下公共方法:

csvreader.__next__
将读者的可迭代对象的下一行作为列表(如果对象是从中返回reader())或dict(如果它是DictReader 实例)返回,根据当前方言进行解析。通常你应该称之为next(reader)

Reader对象具有以下公共属性:

csvreader.dialect
解析器使用的方言的只读描述。
csvreader.line_num
从源迭代器读取的行数。这与返回的记录数不同,因为记录可以跨越多行。

DictReader对象具有以下公共属性:

csvreader.fieldnames
如果在创建对象时未作为参数传递,则在首次访问时或从文件中读取第一条记录时初始化此属性。

csvwriter对象

Writer对象(函数DictWriter返回的实例和对象writer())具有以下公共方法。甲必须是可迭代字符串或数字用于Writer对象和一个字典映射字段名到字符串或数字(通过使它们通过str() 第一)为DictWriter对象。请注意,复数会被parens包围。这可能会导致其他读取CSV文件的程序出现问题(假设它们支持复数)。

csvwriter.writerow
row参数写入writer的文件对象,根据当前方言进行格式化。

版本3.5中已更改:添加了对任意迭代的支持。

csvwriter.writerows
行中的所有元素(如上所述的对象的可迭代)写入编写器的文件对象,根据当前方言进行格式化。

Writer对象具有以下公共属性:

csvwriter.dialect
作者使用的方言的只读描述。

DictWriter对象具有以下公共方法:

DictWriter.writeheader
使用字段名称(在构造函数中指定)写一行。

版本3.2中的新功能。

示例

读取CSV文件的最简单示例:

import csv
with open('some.csv', newline='') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

 

使用备用格式读取文件:

import csv
with open('passwd', newline='') as f:
    reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
    for row in reader:
        print(row)

 

相应的最简单的写作示例是:

import csv
with open('some.csv', 'w', newline='') as f:
    writer = csv.writer(f)
    writer.writerows(someiterable)

 

由于open()用于打开CSV文件进行读取,因此默认情况下使用系统默认编码将文件解码为unicode(请参阅参考资料locale.getpreferredencoding())。要使用不同的编码解码文件,请使用encodingopen 的参数:

import csv
with open('some.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

 

这同样适用于写入系统默认编码以外的其他内容:在打开输出文件时指定encoding参数。

注册新方言:

import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', newline='') as f:
    reader = csv.reader(f, 'unixpwd')

 

稍微更高级的读者使用 – 捕获和报告错误:

import csv, sys
filename = 'some.csv'
with open(filename, newline='') as f:
    reader = csv.reader(f)
    try:
        for row in reader:
            print(row)
    except csv.Error as e:
        sys.exit('file {}, line {}: {}'.format(filename, reader.line_num, e))

 

虽然模块不直接支持解析字符串,但可以轻松完成:

import csv
for row in csv.reader(['one,two,three']):
    print(row)

 

脚注

[1] (1,2)如果newline=''没有指定,嵌入引用字段内换行符将不会被正确地解释,并且在使用平台\r\n上写一个额外linendings \r将被添加。指定应始终是安全的 newline='',因为csv模块执行其自己的(通用)换行处理。