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 Enhancement Proposal提出了对Python的添加。

14.1.1. Module Contents

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. Dialects and Formatting Parameters

为了更容易指定输入和输出记录的格式,特定的格式化参数被分组到方言中。方言是具有一组特定方法和单个validate()方法的Dialect类的子类。当创建readerwriter对象时,程序员可以指定Dialect类的字符串或子类作为方言参数。In addition to, or instead of, the dialect parameter, the programmer can also specify individual formatting parameters, which have the same names as the attributes defined below for the Dialect class.

方言支持以下属性:

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_*常量(参见Module Contents一节),默认为QUOTE_MINIMAL

Dialect.skipinitialspace

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

Dialect.strict

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

14.1.3. Reader Objects

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

csvreader.__next__()

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

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

csvreader.dialect

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

csvreader.line_num

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

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

csvreader.fieldnames

14.1.4. Writer Objects

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)

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

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

csvwriter.writerows(rows)

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

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

csvwriter.dialect

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

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

DictWriter.writeheader()

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

版本3.2中的新功能。

14.1.5. 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文件,因此默认情况下该文件将使用系统默认编码解码为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)换行处理。