Python:CSV文件读取和写入

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

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

CSV模块的读取器和写入器对象读取和写入序列。程序员还可以使用DictReader和DictWriter类以字典形式读取和写入数据。

Python 3:CSV文件读取和写入英文版-新版

Python 2:CSV文件读取和写入英文版-旧版

本篇文章为新版的中文版本。

亦见:
PEP 305 – CSV文件API。
Python增强提案提出了对Python进行此添加的建议。

模块内容

CSV模块定义了以下功能:

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

返回一个读取器对象,该对象将迭代给定csvfile中的行。csvfile可以是任何支持迭代器协议的对象,并在每次调用其__next__()方法时返回一个字符串-文件对象和列表对象都适用。如果csvfile是文件对象,则应使用newline=''打开它。可以给出可选的dialect参数,该参数用于定义特定于特定CSV dialect的一组参数。它可以是dialect类的子类的实例,也可以是LIST_DIACTIONS()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数,以覆盖当前dialect中的各个格式化参数。有关dialect和格式参数的完整详细信息,请参阅“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)

返回一个写入器对象,该写入器对象负责在给定的类似文件的对象上将用户数据转换为分隔字符串。csvfile可以是具有write()方法的任何对象。如果csvfile是文件对象,则应使用newline=''打开它。可以给出可选的dialect参数,该参数用于定义特定于特定CSV dialect的一组参数。它可以是dialect类的子类的实例,也可以是LIST_DIACTIONS()函数返回的字符串之一。可以给出其他可选的fmtparams关键字参数,以覆盖当前dialect中的各个格式化参数。有关dialect和格式参数的完整详细信息,请参阅“Dialects and Formatting Parameters(方言和格式参数)”一节。为了尽可能容易地与实现DBAPI的模块接口,值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和名称联系起来。名称必须是字符串。可以通过传递dialect的子类来指定dialect,也可以通过fmtparams关键字参数指定dialect,也可以同时使用关键字参数覆盖dialect参数来指定dialect。有关dialect和格式参数的完整详细信息,请参阅“Dialects and Formatting Parameters(方言和格式参数)”一节。

csv.unregister_dialect(name)

从dialect注册表中删除与名称关联的dialect。如果名称不是注册的dialect名称,则会引发错误。

csv.get_dialect(name)

返回与名称关联的dialect。如果名称不是注册的dialect名称,则会引发错误。此函数返回不变的dialect。

csv.list_dialects()

返回所有注册dialect的名称。

csv.field_size_limit([new_limit])

返回分析器允许的当前最大字段大小。如果给定了new_limit,则它将成为新的限制。


CSV模块定义以下类:

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

创建一个操作方式与常规读取器类似的对象,但将每行中的信息映射到一个字典,该字典的键由可选的fieldames参数给出。

fieldames参数是一个序列。如果省略fieldname,则文件f第一行中的值将用作字段名。无论字段名是如何确定的,字典都会保留其原始顺序。

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

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

版本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)

创建一个操作方式与常规编写器类似的对象,但将字典映射到输出行。fieldname参数是一个键序列,用于标识传递给writerow()方法的字典中的值写入文件f的顺序。可选的restval参数指定在字典的字段名中缺少键时要写入的值。如果传递给writerow()方法的字典包含在字段名中找不到的键,则可选的extrasaction参数指示要采取的操作。如果它设置为默认值‘raise’,则会引发ValueError。如果将其设置为‘ignore’,则忽略字典中的多余值。任何其他可选参数或关键字参数都将传递给基础编写器实例。

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

以下是一个简短的用法示例:

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类是主要依赖于其属性的容器类,这些属性用于定义特定读取器或写入器实例的参数。

class csv.excel

excel类定义Excel生成的CSV文件的常见属性。它是用dialect名称‘excel’注册的。

class csv.excel_tab

excel_tab类定义Excel生成的TAB分隔文件的常见属性。它是用dialect名称‘excel-tab’注册的。

class csv.unix_dialect

unix_dialect类别定义在UNIX系统上生成的CSV文件的常见属性,即使用‘\n’作为行终止符并引用所有字段。它是用dialect名称“unix”注册的。

3.2版新增。

class csv.Sniffer

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

Sniffer类提供两种方法:

  • sniff(sample, delimiters=None)
    分析给定的示例并返回反映找到的参数的方言子类。如果给出了可选的delimiters参数,则会将其解释为包含可能的有效分隔符字符的字符串。
  • has_header(sample)
    分析示例文本(假定为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

指示写入器对象引用所有字段。

csv.QUOTE_MINIMAL

指示写入器对象仅引用包含特殊字符(如分隔符、引号或行终止符中的任何字符)的字段。

csv.QUOTE_NONNUMERIC

指示写入器对象将所有非数字字段引起来。

指示读取器将所有非引号字段转换为浮点类型。

csv.QUOTE_NONE

指示写入器对象永远不要引用字段。当当前分隔符出现在输出数据中时,它的前面是当前转义字符。如果未设置ESCRECHAR,则在遇到任何需要转义的字符时,编写器将引发错误。

指示读取器不执行引号字符的特殊处理。


CSV模块定义以下异常:

exception csv.Error

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

Dialects and Formatting Parameters(方言和格式参数)

为了更容易地指定输入和输出记录的格式,将特定的格式化参数分组到不同的方言中。dialect是dialect类的子类,它具有一组特定的方法和一个Validation()方法。创建读取器或写入器对象时,程序员可以指定字符串或dialect类的子类作为dialect参数。除了dialect参数之外,或者代替dialect参数,程序员还可以指定各个格式化参数,这些参数与下面为dialect类定义的属性具有相同的名称。

Dialects支持以下属性:

Dialect.delimiter

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

Dialect.doublequote

控制字段内出现的quotechar实例本身的引号方式。如果为True,则字符加倍。如果为False,则将转义字符用作报价字符的前缀。默认为True。

在输出时,如果doublequote为false并且未设置转义字符,则在字段中发现报价字符时将引发错误。

Dialect.escapechar

一个单字符字符串,如果QUOTING设置为QUOTE_NONE,则编写器用于转义分隔符;如果Doublequote设置为False,则用于转义QUOTEChar。在阅读时,换行符从后面的字符中删除任何特殊含义。它的默认值为NONE,这将禁用转义。

Dialect.lineterminator

用于终止由写入器生成的行的字符串。默认为’\r\n’。

注意:读取是硬编码的,可以将‘\r’或‘\n’识别为行尾,并忽略行终止符。这一行为在未来可能会改变。

Dialect.quotechar

用于引用包含特殊字符(如分隔符或引号)或包含换行符的字段的单字符字符串。默认为'”‘。

Dialect.quoting

控制何时应由写入器生成引号并由读取器识别。它可以采用任何QUOTE_*常量(参见模块内容一节),并默认为QUOTE_MINIMAL

Dialect.skipinitialspace

如果为True,则忽略紧跟在分隔符后面的空格。默认值为False。

Dialect.strict

如果为True,则对错误的CSV输入引发异常错误。默认值为False。

读取器对象

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

csvreader.__next__()

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


读取器对象具有以下公共属性:

csvreader.dialect

解析器使用的dialect的只读描述。

csvreader.line_num

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


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

csvreader.fieldnames

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

写入器对象

Writer对象(DictWriter实例和writer()函数返回的对象)具有以下公共方法。对于Writer对象,行必须是字符串或数字的可迭代;对于DictWriter对象,行必须是将字段名映射到字符串或数字(首先通过str()传递它们)的字典。请注意,复数写出时会用括号括起来。这可能会给读取CSV文件的其他程序带来一些问题(假设它们完全支持复数)。

csvwriter.writerow(row)

将ROW参数写入写入器的文件对象,根据当前dialect格式化。返回调用底层文件对象的write方法的返回值。

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

csvwriter.writerows(rows)

将ROWS(如上所述的ROW对象的可迭代)中的所有元素写入写入器的文件对象,并根据当前dialect进行格式化。


写入器对象具有以下公共属性:

csvwriter.dialect

写入器使用的dialect的只读描述。


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

DictWriter.writeheader()

将具有字段名称(在构造函数中指定)的行写入写入器的文件对象,并根据当前dialect格式化。返回内部使用的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.getpreredencoding())。要使用不同的编码对文件进行解码,请使用open的编码参数:

import csv
with open('some.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

这同样适用于写入系统默认编码以外的内容:在打开输出文件时指定编码参数。

注册新dialect:

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)

脚注

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

00

Python

发表评论

邮箱地址不会被公开。 必填项已用*标注

什么阻碍了你实现迈入机器学习领域的目标?

什么阻碍了你实现迈入机器学习领域的目标?

2020-04-22 机器学习

如果你在为进入机器学习领域而挣扎,感觉到有什么东西阻止了自己的开始,那么你应该看看这篇文章。 在这篇文章中,我们会讨论阻止进入机器学习领域的自我限制的信念,让你明白面临的问题。 几乎总是一种自我限制的信念阻碍了你们的进步。 也许你会在一个或多个这样的信念中看到自己。如果是这样的话, [......]

了解详情

R语言机器学习迷你课程

R语言机器学习迷你课程

2020-08-12 机器学习

在这个迷你课程中,你将发现如何开始,构建精确的模型,并自信地完成在14天内使用R预测建模机器学习项目。 这是一个重要而重要的文章。你可能想把它书签。 了解如何准备数据,拟合机器学习模型,并用我的新书评估他们在r上的预测,包括14步教程、3个项目和完整源代码。 我们开始吧。 [......]

了解详情

关于机器学习的几点思考

关于机器学习的几点思考

2020-04-26 机器学习

机器学习是一个大的、跨学科的研究领域。 你可以通过机器学习获得令人印象深刻的结果,并找到非常具有挑战性的问题的解决方案。但这只是更广泛的机器学习领域的一小部分,通常被称为预测建模或预测分析。 在这篇文章中,你将发现如何改变你对机器学习的思考方式,以便更好地为你提供机器学习实践者的服务。 [......]

了解详情

找到你的机器学习部落

找到你的机器学习部落

2020-04-26 机器学习

机器学习是一个充满算法和数据的迷人而强大的研究领域。 问题是,有这么多不同类型的人对机器学习感兴趣,每个人都有不同的需求。重要的是要了解你想要从机器学习中得到什么,并根据这些需求调整你的自学。 如果你不这样做,你很容易就会陷入困境,迷失方向,失去兴趣,得不到你想要的东西。 找到 [......]

了解详情

应用机器学习过程

应用机器学习过程

2020-04-26 机器学习

随着时间的推移,在处理应用机器学习问题时,你会开发出一种模式或流程,以快速获得良好的正常结果。 一旦开发完成,你就可以在一个又一个项目上反复使用此过程。你的流程越健壮、越发达,你就能越快地获得可靠的结果。 在这篇文章中,我想与你分享我解决机器学习问题的过程框架。 你可以将其用作下一 [......]

了解详情