csv
— CSV 文件读取和写入¶
源代码: Lib/csv.py
所谓的 CSV(逗号分隔值)格式是电子表格和数据库最常用的导入和导出格式。在 RFC 4180 中尝试以标准化方式描述该格式之前,CSV 格式已经使用了多年。缺乏明确的标准意味着不同应用程序生成和使用的数据中经常存在细微的差异。这些差异使得处理来自多个来源的 CSV 文件很麻烦。尽管分隔符和引号字符各不相同,但总体格式足够相似,因此可以编写一个可以高效操作此类数据的单个模块,从而向程序员隐藏读取和写入数据的细节。
csv
模块实现了以 CSV 格式读取和写入表格数据的类。它允许程序员说“以 Excel 首选的格式写入此数据”或“从 Excel 生成的此文件中读取数据”,而无需知道 Excel 使用的 CSV 格式的精确细节。程序员还可以描述其他应用程序理解的 CSV 格式或定义他们自己的专用 CSV 格式。
csv
模块的 reader
和 writer
对象读取和写入序列。程序员还可以使用 DictReader
和 DictWriter
类以字典形式读取和写入数据。
另请参阅
- PEP 305 - CSV 文件 API
提议将此添加到 Python 的 Python 增强提案。
模块内容¶
csv
模块定义了以下函数
- csv.reader(csvfile, dialect='excel', **fmtparams)¶
返回一个 reader 对象,该对象将处理给定 csvfile 中的行。 csvfile 必须是字符串的可迭代对象,每个字符串都采用 reader 定义的 csv 格式。 csvfile 通常是类文件对象或列表。如果 csvfile 是文件对象,则应使用
newline=''
打开。[1] 可以提供可选的 dialect 参数,该参数用于定义特定于特定 CSV 方言的一组参数。它可以是Dialect
类的子类的实例,也可以是list_dialects()
函数返回的字符串之一。可以提供其他可选的 fmtparams 关键字参数来覆盖当前方言中的各个格式化参数。有关方言和格式化参数的完整详细信息,请参阅 方言和格式化参数 部分。从 csv 文件读取的每一行都作为字符串列表返回。除非指定了
QUOTE_NONNUMERIC
格式选项(在这种情况下,未加引号的字段将转换为浮点数),否则不会执行自动数据类型转换。一个简短的用法示例
>>> 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.writer(csvfile, dialect='excel', **fmtparams)¶
返回一个 writer 对象,该对象负责将用户的数据转换为给定类文件对象上的分隔字符串。 csvfile 可以是任何具有
write()
方法的对象。如果 csvfile 是文件对象,则应使用newline=''
打开[1]。可以提供可选的 dialect 参数,该参数用于定义特定于特定 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_dialect(name[, dialect[, **fmtparams]])¶
将 dialect 与 name 关联。 name 必须是字符串。可以通过传递
Dialect
的子类、或通过 fmtparams 关键字参数,或两者都指定方言,其中关键字参数会覆盖方言的参数。有关方言和格式化参数的完整详细信息,请参阅 方言和格式化参数 部分。
- csv.list_dialects()¶
返回所有已注册方言的名称。
- csv.field_size_limit([new_limit])¶
返回解析器允许的当前最大字段大小。如果给定 new_limit,则此值将成为新的限制。
csv
模块定义了以下类
- class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)¶
创建一个行为类似于常规读取器的对象,但将每行中的信息映射到一个
dict
,其键由可选的 fieldnames 参数给出。fieldnames 参数是一个 序列。如果省略 fieldnames,则文件 f 的第一行的值将用作字段名,并且将从结果中省略。如果提供了 fieldnames,则将使用它们,并且第一行将包含在结果中。无论如何确定字段名,字典都会保留其原始顺序。
如果某行的字段数多于字段名,则剩余数据将放入列表中,并使用 restkey 指定的字段名存储(默认为
None
)。如果非空白行的字段数少于字段名,则缺失的值将用 restval 的值填充(默认为None
)。所有其他可选或关键字参数都将传递给底层的
reader
实例。如果传递给 fieldnames 的参数是一个迭代器,它将被强制转换为一个
list
。在 3.6 版本中更改: 现在返回的行类型为
OrderedDict
。在 3.8 版本中更改: 现在返回的行类型为
dict
。一个简短的用法示例
>>> 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) {'first_name': 'John', 'last_name': 'Cleese'}
- class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)¶
创建一个行为类似于常规写入器的对象,但将字典映射到输出行。fieldnames 参数是一个
sequence
的键,用于标识传递给writerow()
方法的字典中值的写入文件 f 的顺序。可选的 restval 参数指定如果字典在 fieldnames 中缺少键要写入的值。如果传递给writerow()
方法的字典包含在 fieldnames 中找不到的键,则可选的 extrasaction 参数指示要采取的操作。如果设置为'raise'
(默认值),则会引发ValueError
异常。如果设置为'ignore'
,则会忽略字典中的额外值。任何其他可选或关键字参数都将传递给底层的writer
实例。请注意,与
DictReader
类不同,DictWriter
类的 fieldnames 参数不是可选的。如果传递给 fieldnames 的参数是一个迭代器,它将被强制转换为一个
list
。一个简短的用法示例
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'})
- class csv.Dialect¶
Dialect
类是一个容器类,其属性包含有关如何处理双引号、空格、分隔符等的信息。由于缺乏严格的 CSV 规范,不同的应用程序会产生略有不同的 CSV 数据。Dialect
实例定义了reader
和writer
实例的行为方式。所有可用的
Dialect
名称都由list_dialects()
返回,并且可以通过其初始化器 (__init__
) 函数将其注册到特定的reader
和writer
类,如下所示import csv with open('students.csv', 'w', newline='') as csvfile: writer = csv.writer(csvfile, dialect='unix')
- class csv.unix_dialect¶
unix_dialect
类定义了在 UNIX 系统上生成的 CSV 文件的常用属性,即使用'\n'
作为行终止符并引用所有字段。它使用方言名称'unix'
注册。在 3.2 版本中添加。
- class csv.Sniffer¶
Sniffer
类用于推断 CSV 文件的格式。Sniffer
类提供了两个方法- sniff(sample, delimiters=None)¶
分析给定的sample并返回一个反映所找到参数的
Dialect
子类。如果给定了可选的delimiters参数,则将其解释为包含可能有效的分隔符字符的字符串。
- has_header(sample)¶
分析样本文本(假定为 CSV 格式)并返回
True
如果第一行看起来是一系列列标题。检查每一列,将考虑以下两个关键标准之一来估计样本是否包含标题第二行到第 n 行包含数值
第二行到第 n 行包含字符串,其中至少有一个值的长度与该列的推定标题的长度不同。
采样第一行之后的二十行;如果超过一半的列 + 行满足条件,则返回
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_NONE¶
指示
writer
对象永不引用字段。当当前 delimiter 出现在输出数据中时,它前面会加上当前 escapechar 字符。如果未设置 escapechar,则如果遇到任何需要转义的字符,写入器将引发Error
。指示
reader
对象不对引号字符执行任何特殊处理。
- csv.QUOTE_NOTNULL¶
指示
writer
对象引用所有不是None
的字段。这与QUOTE_ALL
类似,只是如果字段值为None
,则会写入一个空(未引用)的字符串。指示
reader
对象将空(未引用)的字段解释为None
,否则其行为与QUOTE_ALL
相同。在 3.12 版本中添加。
- csv.QUOTE_STRINGS¶
指示
writer
对象始终在字符串字段周围放置引号。这与QUOTE_NONNUMERIC
类似,只是如果字段值为None
,则会写入一个空(未引用)的字符串。指示
reader
对象将空(未引用)的字符串解释为None
,否则其行为与QUOTE_NONNUMERIC
相同。在 3.12 版本中添加。
csv
模块定义了以下异常
- exception csv.Error¶
当检测到错误时,任何函数都会引发此异常。
方言和格式化参数¶
为了更容易指定输入和输出记录的格式,特定的格式化参数被分组到方言中。方言是 Dialect
类的子类,其中包含描述 CSV 文件格式的各种属性。创建 reader
或 writer
对象时,程序员可以指定一个字符串或 Dialect
类的子类作为方言参数。除了或代替 dialect 参数,程序员还可以指定单个格式化参数,这些参数的名称与下面为 Dialect
类定义的属性相同。
方言支持以下属性
- Dialect.delimiter¶
用于分隔字段的单字符字符串。它默认为
','
。
- Dialect.doublequote¶
控制如何引用出现在字段内的 quotechar 实例。当
True
时,该字符会加倍。当False
时,escapechar 用作 quotechar 的前缀。它默认为True
。在输出时,如果 doublequote 为
False
并且未设置 escapechar,则如果在字段中找到 quotechar,将引发Error
。
- Dialect.escapechar¶
一个单字符字符串,当quoting设置为
QUOTE_NONE
,且当doublequote为False
时,由写入器用于转义delimiter或quotechar。 在读取时,escapechar 会删除后续字符的任何特殊含义。 它默认为None
,表示禁用转义。3.11 版本已更改: 不允许使用空的 escapechar。
- Dialect.lineterminator¶
用于终止
writer
生成的行的字符串。 它默认为'\r\n'
。注意
reader
被硬编码为识别'\r'
或'\n'
作为行尾,并忽略 lineterminator。 此行为在未来可能会更改。
- Dialect.quotechar¶
用于引用包含特殊字符(例如 delimiter 或 quotechar)或包含换行符的字段的单字符字符串。 它默认为
'"'
。3.11 版本已更改: 不允许使用空的 quotechar。
- Dialect.quoting¶
控制写入器何时生成引号以及读取器何时识别引号。 它可以采用任何 QUOTE_* 常量,并默认为
QUOTE_MINIMAL
。
读取器对象¶
读取器对象(DictReader
实例和 reader()
函数返回的对象)具有以下公共方法
- csvreader.__next__()¶
以列表形式(如果对象是从
reader()
返回的)或字典形式(如果它是DictReader
实例)返回读取器的可迭代对象的下一行,并根据当前的Dialect
进行解析。 通常你应该将其作为next(reader)
调用。
读取器对象具有以下公共属性
- csvreader.dialect¶
一个对解析器使用的方言的只读描述。
- csvreader.line_num¶
从源迭代器读取的行数。 这与返回的记录数不同,因为记录可以跨越多行。
DictReader 对象具有以下公共属性
- DictReader.fieldnames¶
如果未在创建对象时作为参数传递,则此属性将在首次访问或从文件中读取第一条记录时初始化。
写入器对象¶
writer
对象(DictWriter
实例和 writer()
函数返回的对象)具有以下公共方法。 对于 writer
对象,row 必须是字符串或数字的可迭代对象,对于 DictWriter
对象,row 必须是将字段名称映射到字符串或数字的字典(首先通过 str()
传递它们)。 请注意,复数会用括号括起来写入。 这可能会给其他读取 CSV 文件的程序带来一些问题(假设它们完全支持复数)。
- csvwriter.writerow(row)¶
根据当前的
Dialect
将 row 参数写入写入器的文件对象。 返回对底层文件对象的 write 方法的调用返回值。3.5 版本已更改: 添加了对任意可迭代对象的支持。
- csvwriter.writerows(rows)¶
根据当前方言将 rows 中的所有元素(一个如上所述的 row 对象的可迭代对象)写入写入器的文件对象。
写入器对象具有以下公共属性
- csvwriter.dialect¶
一个对写入器使用的方言的只读描述。
DictWriter 对象具有以下公共方法
- DictWriter.writeheader()¶
将包含字段名称(如构造函数中指定)的行写入写入器的文件对象,并根据当前的方言进行格式化。 返回内部使用的
csvwriter.writerow()
调用的返回值。在 3.2 版本中添加。
3.8 版本已更改:
writeheader()
现在还返回其内部使用的csvwriter.writerow()
方法的返回值。
示例¶
读取 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 文件进行读取,该文件默认会使用系统默认编码(请参阅 locale.getencoding()
)解码为 unicode。 要使用不同的编码解码文件,请使用 open 的 encoding
参数
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)
脚注