csv — CSV 文件读写

源代码: Lib/csv.py


所谓的 CSV(逗号分隔值)格式是电子表格和数据库最常用的导入和导出格式。try使用 RFC 4180以标准化方式描述格式之前,CSV 格式已经使用了很多年。缺乏明确定义的标准意味着在不同应用程序生成和使用的数据中经常存在细微的差异。这些差异会使处理来自多个来源的 CSV 文件变得烦人。尽管如此,尽管定界符和引号字符有所不同,但总体格式足够相似,因此有可能编写一个可以有效处理此类数据的模块,从而隐藏了对程序员进行数据读写的细节。

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

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

See also

  • PEP 305-CSV 文件 API

  • 《 Python 增强提案》提出了对 Python 的这一补充。

Module Contents

csv模块定义以下Function:

  • csv. reader(* csvfile dialect ='excel'** fmtparams *)
    • 返回一个读取器对象,该对象将遍历给定* csvfile *中的行。 * csvfile 可以是任何支持iterator协议并在每次__next__()方法被调用为file objects时都返回字符串的对象,并且列表对象均适用。如果 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 *]])

    • 方言与* name *相关联。 * name 必须为字符串。可以pass传递Dialect的子类或pass fmtparams *关键字参数(或两者都使用关键字参数覆盖方言的参数)来指定方言。有关方言和格式设置参数的完整详细信息,请参见方言和格式参数部分。
  • csv. unregister_dialect(* name *)

    • 从方言注册表中删除与* name 关联的方言。如果 name *不是注册的方言名称,则会引发Error
  • csv. get_dialect(* name *)

    • 返回与* name 关联的方言。如果 name *不是注册的方言名称,则会引发Error。此函数返回一个不变的Dialect
  • 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 *)
    • 创建一个操作类似于常规读取器的对象,但将每行中的信息 Map 到dict,其键由可选的* fieldnames *参数给出。
  • fieldnames 参数是sequence。如果Ellipsis fieldnames ,则文件 f *第一行中的值将用作字段名。不管如何确定字段名,字典都将保留其原始 Sequences。

如果行中的字段多于字段名,则其余数据将放入列表中,并以* restkey (默认值为None)指定的字段名存储。如果非空白行的字段少于字段名,则缺少的值将用 restval *的值(默认为None)填充。

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

在版本 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 *)
    • 创建一个操作类似于常规编写器的对象,但将字典 Map 到输出行。参数* fieldnames 是一个sequence键,这些键标识传递给writerow()方法的字典中的值写入文件 f 的 Sequences。可选的 restval 参数指定如果字典缺少 fieldnames 中的键时要写入的值。如果传递给writerow()方法的词典包含在 fieldnames 中找不到的键,则可选的 extrasaction *参数指示要执行的操作。如果将其设置为'raise',则默认值为ValueError。如果将其设置为'ignore',则字典中的其他值将被忽略。其他任何可选参数或关键字参数都将传递到基础writer实例。

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

一个简短的用法示例:

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 生成的 TAB 分隔文件的常规属性。它以方言名称'excel-tab'注册。
  • 类别 csv. unix_dialect

    • unix_dialect类定义了在 UNIX 系统上生成的 CSV 文件的常规属性,即使用'\n'作为行终止符并引用所有字段。它以方言名称'unix'注册。

3.2 版中的新Function。

  • 类别 csv. Sniffer
    • Sniffer类用于推断 CSV 文件的格式。

Sniffer类提供了两种方法:

  • sniff(* sample delimiters = None *)

    • 分析给定的* sample 并返回一个Dialect子类,以反映找到的参数。如果给出了可选的 delimiters *参数,则将其解释为包含可能的有效分隔符的字符串。
  • has_header(samples)

    • 分析示例文本(假定为 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对象仅引用包含特殊字符(例如* delimiter quotechar lineterminator *中的任何字符)的字段。
  • csv. QUOTE_NONNUMERIC

    • 指示writer对象引用所有非数字字段。

指示 Reader 将所有未引用的字段转换为* float *类型。

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

指示reader不对引号字符进行特殊处理。

csv模块定义以下异常:

  • exception csv. Error
    • 检测到错误时由任何Function引发。

方言和格式参数

为了更轻松地指定 Importing 和输出记录的格式,将特定的格式设置参数组合为方言。方言是Dialect类的子类,它具有一组特定方法和一个validate()方法。创建readerwriter对象时,程序员可以将字符串或Dialect类的子类指定为方言参数。除了* dialect *参数以外,程序员还可以指定各个格式设置参数,这些参数的名称与下面为Dialect类定义的属性相同。

方言支持以下属性:

  • Dialect. delimiter

    • 一个用于分隔字段的单字符字符串。默认为','
  • Dialect. doublequote

    • 控制出现在字段中的* quotechar 实例本身应如何被引用。当True时,字符加倍。当False时, escapechar 用作 quotechar *的前缀。默认为True

在输出时,如果* doublequote False且未设置 escapechar ,则如果在字段中找到 quotechar *,则引发Error

  • Dialect. escapechar

    • 如果将* quoting 设置为QUOTE_NONE,则编写者使用一个单字符字符串来转义 delimiter ,如果 doublequote False,则使用 quotechar 。阅读时, escapechar *会删除下一个字符中的所有特殊含义。它默认为None,这将禁用转义。
  • Dialect. lineterminator

    • 用于终止writer产生的行的字符串。默认为'\r\n'

Note

reader被硬编码为将'\r''\n'识别为行尾,并忽略* lineterminator *。这种行为将来可能会改变。

  • Dialect. quotechar

    • 一个单字符字符串,用于引用包含特殊字符(例如* delimiter quotechar *)或包含换行符的字段。默认为'"'
  • Dialect. quoting

    • 控制引号何时由作者生成并由 Reader 识别。它可以采用任何QUOTE_*常量(请参见Module Contents),默认为QUOTE_MINIMAL
  • Dialect. skipinitialspace

    • True时,紧跟在* delimiter *之后的空格将被忽略。默认值为False
  • Dialect. strict

    • True时,对于错误的 CSVImporting,引发异常Error。默认值为False

Reader Objects

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

  • csvreader. __next__ ( )
    • 返回读取器的可迭代对象的下一行作为列表(如果该对象是从reader()返回的)或字典(如果它是DictReader实例),则根据当前的方言进行解析。通常,您应将其称为next(reader)

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

  • csvreader. dialect

    • 解析器使用的方言的只读描述。
  • csvreader. line_num

    • 从源迭代器读取的行数。这与返回的记录数不同,因为记录可以跨越多行。

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

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

Writer Objects

Writer个对象(DictWriter个实例和writer()函数返回的对象)具有以下公共方法。 对于Writer对象必须是字符串或数字的可迭代项,并且对于DictWriter对象必须是将字段名 Map 为字符串或数字(首先passstr()传递)的字典。请注意,复数写在括号内。这可能会给其他读取 CSV 文件的程序带来一些问题(假设它们完全支持复数)。

  • csvwriter. writerow(* row *)
    • 将* row 参数写入编写者的文件对象,并根据当前方言格式化。将调用的返回值返回到基础文件对象的 write *方法。

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

  • csvwriter. writerows()
    • 将* rows(如上所述,* row *对象的迭代)中的所有元素写入编写者的文件对象,并根据当前方言格式化。

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

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

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

  • DictWriter. writeheader ( )
    • 将具有字段名称(在构造函数中指定)的行写入编写者的文件对象,并根据当前方言格式化。返回内部使用的csvwriter.writerow()调用的返回值。

3.2 版中的新Function。

在 3.8 版中进行了更改:writeheader()现在还返回了它内部使用的csvwriter.writerow()方法返回的值。

Examples

读取 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.getpreferredencoding())解码为 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)

Footnotes

  • 1 (1,2)
    • 如果未指定newline='',则引号字段中嵌入的换行符将无法正确解释,并且在使用\r\n linendings 的平台上将添加额外的\r。指定newline=''应该总是安全的,因为 csv 模块会执行自己的(universal)换行符处理。