14.1. csv - CSV文件读取和写入

源代码: Lib / csv.py

所谓的CSV(Comma Separated Values)格式是电子表格和数据库最常见的导入和导出格式。在尝试以 RFC 4180以标准化方式描述格式之前,CSV格式已使用多年。The lack of a well-defined standard means that subtle differences often exist in the data produced and consumed by different applications.这些差异可能会让处理来自多个来源的CSV文件烦人。尽管分隔符和引用字符不同,但是整体格式是足够相似的,以致于可以编写能够有效地操作这样的数据的单个模块,隐藏从编程器读取和写入数据的细节。

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

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

也可以看看

PEP 305 - CSV文件API
Python 改善建议书 提出了对Python的添加。

14.1.1. 模块内容

csv模块定义以下函数:

csv.reader(csvfile, dialect='excel', **fmtparams)

返回一个读取器对象,它将在给定的csvfile中迭代。csvfile可以是任何支持iterator协议的对象,并且每次调用__next__()方法时返回一个字符串 - file objects和列表对象都是合适的。如果csvfile是文件对象,则应使用newline=''打开它。[1]可以给出一个可选的方言参数,用于定义特定于某个CSV方言的一组参数。它可以是Dialect类的子类的实例或list_dialects()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数以覆盖当前方言(方言译为”编码分格“更好)中的各个格式化参数。有关方言和格式化参数的完整详细信息,请参见Dialects and Formatting Parameters一节。

从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]打开。可以给出可选的方言参数,用于定义特定于特定CSV方言的一组参数。它可以是Dialect类的子类的实例或list_dialects()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数以覆盖当前方言中的各个格式化参数。有关方言和格式化参数的完整详细信息,请参见Dialects and Formatting Parameters一节。为了尽可能容易地与实现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的子类或fmtparams关键字参数或两者来指定,其中关键字参数覆盖方言的参数。有关方言和格式化参数的完整详细信息,请参见Dialects and Formatting Parameters一节。

csv.unregister_dialect(name)

从方言注册表中删除与名称关联的方言。如果名称不是注册的方言名称,则会引发Error

csv.get_dialect(name)

返回与名称关联的方言。如果名称不是注册的方言名称,则会引发Error此函数返回不可变的Dialect

csv.list_dialects()

返回所有注册方言的名称。

csv.field_size_limit([new_limit])

返回解析器允许的当前最大字段大小。如果给出new_limit,则这将成为新限制。

csv模块定义以下类:

class csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)

创建一个对象,其操作类似于普通读取器,但将读取的信息映射到一个dict中,其中的键由可选的fieldnames参数给出。fieldnames参数是一个sequence,其元素按顺序与输入数据的字段相关联。这些元素成为结果字典的键。如果省略fieldnames参数,则csvfile的第一行中的值将用作字段名称。如果读取的行具有比字段名序列更多的字段,则剩余数据将作为键值为restkey的序列添加。如果读取的行具有比字段名序列少的字段,则剩余的键使用可选的restval参数的值。任何其他可选或关键字参数都传递给底层的reader实例。

简短用法示例:

>>> import csv
>>> with open('names.csv') as csvfile:
...     reader = csv.DictReader(csvfile)
...     for row in reader:
...         print(row['first_name'], row['last_name'])
...
Baked Beans
Lovely Spam
Wonderful Spam
class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)

创建一个操作类似于常规writer的对象,但将字典映射到输出行。fieldnames参数是一个sequence,用于标识传递给writerow()方法的字典中的值被写入csvfile如果字典在fieldnames中缺少键,则可选的restval参数指定要写入的值。如果传递给writerow()方法的字典包含fieldnames中未找到的键,则可选的extrasaction参数指示要执行的操作。如果设置为'raise',则会引发ValueError如果设置为'ignore',则会忽略字典中的额外值。任何其他可选或关键字参数都传递给底层的writer实例。

请注意,与DictReader类不同,DictWriterfieldnames参数不是可选的。由于Python的dict对象没有排序,因此没有足够的信息来推断将该行写入到csvfile的顺序。

简短用法示例:

import csv

with open('names.csv', 'w') 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类是主要依赖于其属性的容器类,用于定义特定readerwriter实例的参数。

class csv.excel

excel类定义Excel生成的CSV文件的常用属性。它用方言名称'excel'注册。

class csv.excel_tab

excel_tab类定义了Excel生成的TAB分隔文件的常用属性。它用方言名称'excel-tab'注册。

class csv.unix_dialect

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

版本3.2中的新功能。

class csv.Sniffer

Sniffer类用于推导CSV文件的格式。

Sniffer类提供两种方法:

sniff(sample, delimiters=None)

分析给定的示例并返回一个反映所找到的参数的Dialect子类。如果给出了可选的分隔符参数,它将被解释为包含可能的有效分隔符字符的字符串。

has_header(sample)

分析示例文本(假定为CSV格式),如果第一行显示为一系列列标题,则返回True

Sniffer的示例使用:

with open('example.csv') 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对象仅引用包含特殊字符(如分隔符quotecharlineterminator t5>。

csv.QUOTE_NONNUMERIC

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

指示读者将所有未引用的字段转换为float

csv.QUOTE_NONE

指示writer对象从不引用字段。当输出数据中出现当前定界符时,其前面为当前escapechar字符。如果未设置escapechar,如果遇到需要转义的字符,则写入程序将引发Error

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

csv模块定义了以下异常:

exception csv.Error

检测到错误时由任何函数引发。

14.1.2. 方言和格式参数

为了更容易指定输入和输出记录的格式,特定的格式化参数被分组到方言中。方言是具有一组特定方法和单个validate()方法的Dialect类的子类。当创建readerwriter对象时,程序员可以指定Dialect类的字符串或子类作为方言参数。除了dialect参数外,程序员还可以指定单独的格式参数,它们与Dialect类的下面定义的属性具有相同的名称。

方言支持以下属性:

Dialect.delimiter

用于分隔字段的单字符字符串。它默认为','

Dialect.doublequote

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

On output, if doublequote is False and no escapechar is set, Error is raised if a quotechar is found in a field.

Dialect.escapechar

写入器将分隔符(如果引用)转义的一个字符串设置为QUOTE_NONEquotechar如果doublequoteFalse读取时,escapechar会删除以下字符中的任何特殊含义。它默认为None,它禁用转义。

Dialect.lineterminator

用于终止由writer生成的行的字符串。它默认为'\r\n'

注意

reader是硬编码的,以识别'\r''\n'作为行尾,并忽略 lineterminator此行为可能会在将来更改。

Dialect.quotechar

用于引用包含特殊字符(例如分隔符quotechar)或包含换行字符的字段的单字符字符串。它默认为'"'

Dialect.quoting

控制当quote应由writer生成并由reader识别。它可以接受任何QUOTE_*常量(参见Module Contents一节),默认为QUOTE_MINIMAL

Dialect.skipinitialspace

True时,紧跟分隔符后的空格将被忽略。默认值为False

Dialect.strict

True时,在错误的CSV输入上引发异常Error默认值为False

14.1.3. Reader 对象

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

csvreader.__next__()

返回Reader的可迭代对象的下一行作为列表,根据当前方言解析。通常你应该把它叫做next(reader)

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

csvreader.dialect

解析器使用的方言的只读描述。

csvreader.line_num

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

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

csvreader.fieldnames

14.1.4. Writer 对象

Writer对象(DictWriter实例和由writer()函数返回的对象)具有以下公共方法。A row must be an iterable of strings or numbers for Writer objects and a dictionary mapping fieldnames to strings or numbers (by passing them through str() first) for DictWriter objects. 注意,复数用柔义包围。这可能会导致一些问题,其他程序读取CSV文件(假设他们支持复数)。

csvwriter.writerow(row)

将参数row写入写入器的文件对象,根据当前方言格式化。

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

csvwriter.writerows(rows)

将所有参数(如上所述的对象的列表)写入writer的文件对象,根据当前方言格式化。

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

csvwriter.dialect

Writer使用的方言的只读描述。

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

DictWriter.writeheader()

用字段名写入一行(在构造函数中指定)。

版本3.2中的新功能。

14.1.5. 实例¶ T0>

读取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()) 。要使用不同的编码对文件进行解码,请使用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)

脚注

[1]12如果未指定newline=''将正确解释,在使用\r\n linendings写入额外\r的平台上将被添加。指定newline=''应该是安全的,因为csv模块有自己的(universal)换行处理。