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='excel', **fmtparams)¶
将 dialect 与 name 关联。name 必须是字符串。方言可以通过传递
Dialect
的子类,或通过 fmtparams 关键字参数,或两者兼有来指定,其中关键字参数会覆盖方言的参数。有关方言和格式化参数的完整详细信息,请参见 方言和格式化参数 部分。
- csv.list_dialects()¶
返回所有已注册方言的名称。
- csv.field_size_limit()¶
- csv.field_size_limit(new_limit)
返回解析器当前允许的最大字段大小。如果给定了 new_limit,它将成为新的限制。
csv
模块定义了以下类
- class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)¶
创建一个类似于常规 reader 的对象,但将每行中的信息映射到一个
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)¶
创建一个类似于常规 writer 的对象,但将字典映射到输出行。fieldnames 参数是一个键的
序列
,用于标识传递给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_MINIMAL¶
指示
writer
对象仅引用那些包含特殊字符(如 delimiter、quotechar、'\r'
、'\n'
或 lineterminator 中的任何字符)的字段。
- csv.QUOTE_NONNUMERIC¶
指示
writer
对象引用所有非数字字段。指示
reader
对象将所有未加引号的字段转换为float
类型。备注
某些数值类型,如
bool
、Fraction
或IntEnum
,其字符串表示无法转换为float
。它们无法在QUOTE_NONNUMERIC
和QUOTE_STRINGS
模式下读取。
- csv.QUOTE_NONE¶
指示
writer
对象从不引用字段。当当前的 delimiter、quotechar、escapechar、'\r'
、'\n'
或 lineterminator 中的任何字符出现在输出数据中时,它前面会加上当前的 escapechar 字符。如果未设置 escapechar,则在遇到任何需要转义的字符时,writer 将引发Error
。将 quotechar 设置为None
> 以防止其转义。指示
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¶
writer 用于转义需要转义的字符的单字符字符串
如果 quoting 设置为
QUOTE_NONE
,则 delimiter、quotechar、'\r'
、'\n'
和 lineterminator 中的任何字符都会被转义;如果 doublequote 为
False
,则 quotechar 会被转义;escapechar 本身。
读取时,escapechar 会移除其后字符的任何特殊含义。它默认为
None
,表示禁用转义。在 3.11 版本发生变更: 不允许空的 escapechar。
- Dialect.lineterminator¶
用于终止
writer
生成的行的字符串。默认为'\r\n'
。备注
reader
硬编码为识别'\r'
> 或'\n'
作为行尾,并忽略 lineterminator。此行为将来可能会改变。
- Dialect.quotechar¶
用于引用包含特殊字符(如 delimiter 或 quotechar)或包含换行符(
'\r'
、'\n'
或 lineterminator 中的任何字符)的字段的单字符字符串。默认为'"'
。如果 quoting 设置为QUOTE_NONE
,可以设置为None
> 以防止转义'"'
。在 3.11 版本发生变更: 不允许空的 quotechar。
- Dialect.quoting¶
控制 writer 何时生成引号以及 reader 何时识别引号。它可以是任何 QUOTE_* 常量,如果 quotechar 不是
None
,则默认为QUOTE_MINIMAL
,否则默认为QUOTE_NONE
。
Reader 对象¶
Reader 对象(DictReader
实例和由 reader()
函数返回的对象)具有以下公共方法
- csvreader.__next__()¶
返回 reader 的可迭代对象的下一行,格式为列表(如果对象是从
reader()
返回的)或字典(如果它是DictReader
实例),并根据当前的Dialect
进行解析。通常你应该以next(reader)
> 的形式调用它。
Reader 对象具有以下公共属性
- csvreader.dialect¶
解析器使用的方言的只读描述。
- csvreader.line_num¶
从源迭代器读取的行数。这与返回的记录数不同,因为记录可以跨越多行。
DictReader 对象具有以下公共属性
- DictReader.fieldnames¶
如果在创建对象时未作为参数传递,此属性会在首次访问或从文件中读取第一条记录时初始化。
Writer 对象¶
writer
对象(DictWriter
实例和由 writer()
函数返回的对象)具有以下公共方法。对于 writer
对象,row 必须是字符串或数字的可迭代对象;对于 DictWriter
对象,row 必须是将字段名映射到字符串或数字的字典(通过先传递给 str()
)。请注意,复数会用括号括起来写入。这可能会给其他读取 CSV 文件的程序带来一些问题(假设它们支持复数)。
- csvwriter.writerow(row, /)¶
将 row 参数写入 writer 的文件对象,并根据当前的
Dialect
进行格式化。返回底层文件对象的 write 方法调用的返回值。在 3.5 版本发生变更: 增加了对任意可迭代对象的支持。
- csvwriter.writerows(rows, /)¶
将 rows(一个如上所述的 row 对象的可迭代对象)中的所有元素写入 writer 的文件对象,并根据当前方言进行格式化。
Writer 对象具有以下公共属性
- csvwriter.dialect¶
writer 使用的方言的只读描述。
DictWriter 对象具有以下公共方法
- DictWriter.writeheader()¶
将一行带有字段名(在构造函数中指定)的数据写入 writer 的文件对象,并根据当前方言进行格式化。返回内部使用的
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 文件进行读取,因此默认情况下,文件将使用系统默认编码解码为 unicode(参见 locale.getencoding()
)。要使用不同的编码解码文件,请使用 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')
一个更高级的 reader 用法——捕获和报告错误
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(f'file {filename}, line {reader.line_num}: {e}')
虽然该模块不直接支持解析字符串,但可以很容易地实现
import csv
for row in csv.reader(['one,two,three']):
print(row)
脚注