新版本 2.3。
所谓的 CSV(Comma Separated Values)格式是电子表格和数据库导入和导出最常见的格式。实际上并不存在"CSV 标准",因此CSV文件的格式在操作中往往由许多读写它的应用程序定义。缺乏一个通用的CSV标准意味着:不同的应用程序生成和使用的数据通常会有些细微的差异。这些差异会使得处理出自多种来源的 CSV 文件让人相当恼火。尽管分隔符和引用字符不同,但是整体格式也足够相似,可以编写一个可以有效地操纵这些数据的单个模块,从编程器中隐藏读取和写入数据的细节。
csv模块实现类来读取和写入 CSV 格式的表格数据。它允许程序员“以Excel 首选的格式写入此数据"或"从Excel 生成的文件中读取数据",而不用知道 Excel 使用的 CSV 格式的具体细节。程序员也可以描述由其他应用程序理解的 CSV 格式或定义它们自己特殊用途的 CSV 格式。
csv 模块的reader和writer对象读取和写入序列。程序员也可以使用DictReader和DictWriter类读取和写入字典形式的数据。
注
此版本的 csv 模块不支持 Unicode 的输入。此外,目前有一些关于 ASCII NUL 字符的问题。因此,为了安全起见,所有输入应该都是UTF-8 或可打印的 ASCII;请参见示例一节中的示例。
请参见
csv 模块定义了以下函数:
返回一个reader 对象,它将遍历csvfile中的每一行。csvfile可以是任何支持迭代器协议的对象,每次调用它的next()方法时返回一个字符串 —— 文件对象和列表对象都可以。如果csvfile是一个文件对象,在'b'标志对于打开文件有所有不同的平台上,它必须带有该标志。dialect 是一个可选参数,用于定义一个特定CSV 程序的参数集。它可以是Dialect类的子类的一个实例,或者list_dialects()函数返回的字符串中的一个。可以指定另外一个可选的关键字参数fmtparams来覆盖当前dialect中的格式设置参数。关于dialect和格式设置参数的全部细节,请参阅Dialects and Formatting Parameters一节。
从 csv 文件中读取的每一行作为一个字符串列表返回。不执行任何自动数据类型转换。
一个简短的用法示例:
>>> import csv
>>> with open('eggs.csv', 'rb') 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
2.5 版本中的更改:解析器对于多行引用的字段现在变得更加严格。以前,如果一行结束在无终止的换行字符的引用字段内,换行符将插入到的返回的字段。读取文件,其中载有马车返回字段内的字符时,这种行为造成问题。行为更改为返回的字段,而不插入换行符。因此,如果换行符嵌入领域很重要的输入应分成行保留换行符字符的方式。
返回一个writer对象,负责将用户的数据转换为分隔字符串并写入给定的类文件对象中。csvfile可以是任何带有write()方法的对象。如果csvfile是一个文件对象,在'b'标志对于打开文件有所有不同的平台上,它必须带有该标志。dialect 是一个可选参数,用于定义一个特定CSV 程序的参数集。它可以是Dialect类的子类的一个实例,或者list_dialects()函数返回的字符串中的一个。可以指定另外一个可选的关键字参数fmtparams来覆盖当前dialect中的格式设置参数。关于dialect和格式设置参数的全部细节,请参阅Dialects and Formatting Parameters一节。为了使它尽可能容易地与实现 DB API 的模块通信,None 值被作为空字符串写入。虽然这不是一个可逆转变,这使得它更容易转储SQL NULL 数据值到CSV 文件中,而不用先处理一下cursor.fetch*调用返回的数据。所有其它非字符串数据在写入之前利用str()进行字符串化。
一个简短的用法示例:
import csv
with open('eggs.csv', 'wb') 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'])
将dialect与name相关联。name must be a string or Unicode object.dialect 可以通过传递Dialect的一个子类或者fmtparams关键字参数指定,或者两者同时指定,此时关键字参数将覆盖dialect 的参数。关于dialect和格式设置参数的全部细节,请参阅Dialects and Formatting Parameters一节。
返回与name相关联的dialect。如果name不是注册过的dialect名称,将引发一个Error。
2.5 版本中的更改:现在,此函数返回一个不可变的Dialect。以前返回请求的dialect 的一个实例。用户可以修改基础类,借此改变活动的reader 和writer 的行为。
返回所有已注册的dialect 的名称。
返回解析器当前允许的最大字段大小。如果给出了new_limit ,这将成为新的限制。
版本 2.5 中新增。
csv 模块定义了以下类:
创建一个对象,它的操作类似一个普通的reader,但将读取的信息映射成一个字典,字典的键通过可选的参数fieldnames给出。fieldnames参数是一个序列,其元素与输入数据的字段与按顺序相关联。这些元素成为产生的字典的键。如果省略fieldnames参数,csvfile的第一行的值将用作fieldnames。如果读取的行字段数要多于字段名序列,剩下的数据将添加成一个序列,通过restkey的值索引。如果读取的行的字段数少于fieldnames序列,剩余的键将作为可选的restval参数的值。任何其它可选或关键字参数将传递给底层的reader实例。
创建一个对象,它的操作类似一个普通的writer,但将字典映射至行输出(output rows)。字段名参数是标识的顺序传递给writerow()方法的字典中的值写入csvfile键的序列。可选的restval参数指定要写入如果字典缺少中字段名的键的值。如果传递给writerow()方法的字典包含字段名中找不到钥匙,可选extrasaction参数指示采取什么行动。如果设置为'raise',则会引发ValueError。如果设置为'ignore',则会忽略字典中的额外值。任何其他可选或关键字参数都会传递给底层的writer实例。
请注意,与DictReader类不同, DictWriter的字段名参数不是可选的。由于 Python 的dict对象不排序的不是足够的信息,可用来推断应将行写入csvfile的顺序。
Sniffer类用来推断 CSV 文件的格式。
Sniffer类提供两种方法:
一个使用Sniffer的例子:
with open('example.csv', 'rb') as csvfile:
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
# ... process CSV file contents here ...
csv模块定义了下列常量:
指示writer 对象永远不引用字段。当前的delimiter出现在输出数据中时,会在它前面加上一个前导的escapechar字符。如果未设置escapechar ,遇到任何要求转义的字符时,writer 将引发Error。
指示reader 不用对引号字符做特殊处理。
csv 模块定义了以下异常:
任何函数中检测到错误时抛出。
为了便于指定输入和输出记录的格式,具体格式参数被组合成方言。方言是有一套具体的方法和一种单一validate ()方法的方言类的子类。创建读取器或编写器对象时,程序员可以作为方言参数指定一个字符串或方言类的子类。以增补或代替方言参数,程序员也可以指定单个格式的参数,具有相同的定义下面方言类的属性的名称。
Dialects 支持以下属性:
用于分隔字段的单字符字符串。它默认为','。
控制如何quotechar字段内出现的实例应该是被自己被引述。当True,人物是翻了一番。当False, escapechar是作为quotechar的前缀的使用。其默认值为True。
对输出,如果doublequote为False ,并且设置没有escapechar ,则引发错误如果quotechar在一个字段中找到。
这位作家用于转义分隔符,如果引用设置为QUOTE_NONE和quotechar doublequote为False时的单字符字符串。在读时, escapechar从以下字符中移除任何特殊的意义。它将默认为无,这将禁用转义。
用来终止作家所生产出来的行的字符串。它将默认为''.
注
读者是硬编码来识别或''或' '作为结束的行,并忽略lineterminator。这种行为可能在将来会改变。
A one-character string used to quote fields containing special characters, such as the delimiter or quotechar, or which contain new-line characters. It defaults to '"'.
当报价应由作者生成,并由读者认可的控件。它可以在任何QUOTE_ * (参见部分模块内容) 的常量和默认值为QUOTE_MINIMAL。
Reader 对象(DictReader的实例和reader()函数返回的对象)具有下列公共方法:
以列表形式返回该reader 的可迭代对象的下一行,依据当前的dialect 解析。
Reader 对象具有下列公共属性:
解析器正在使用的dialect 的一个只读描述。
从源迭代器读取的行数。不,这是作为记录可以跨多个行,返回的记录的数目相同。
新版本 2.5 中的。
DictReader 对象具有下列公共属性:
如果不作为参数传递,创建对象时,此属性被初始化后第一次访问或当从文件中读取第一个记录。
在 2.6 版本中更改。
Writer对象(DictWriter的实例和writer()函数返回的对象)有下列公开方法。row对于Writer对象必须是一个字符串或数字序列,对于DictWriter对象必须是一个字典,映射字段名到字符串或数字(首先将它们传递给str())。请注意,复数写出时由括号包围。这可能会导致其它读取CSV 文件的程序出现一些问题 (假设它们完全支持复数)。
将row 参数写入writer 的文件对象,格式依据当前的dialect。
写入所有的rows参数(一个上文所述的row对象的列表)到writer 的文件对象,格式依据当前的dialect。
Writer 对象具有下列公共属性:
Writer 正在使用的dialect 的一个只读描述。
DictWriter 对象具有下面的公共方法:
写一个字段名称行(在构造函数中指定)。
在 2.7 版本中新增。
读一个 CSV 文件的最简单的例子:
import csv
with open('some.csv', 'rb') as f:
reader = csv.reader(f)
for row in reader:
print row
读具有另一种格式的文件:
import csv
with open('passwd', 'rb') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
print row
相应的简单可能写作示例是:
import csv
with open('some.csv', 'wb') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
注册一种新方言:
import csv
csv.register_dialect('unixpwd', delimiter=':', quoting=csv.QUOTE_NONE)
with open('passwd', 'rb') as f:
reader = csv.reader(f, 'unixpwd')
读者一个稍微更先进的用途 — — 捕捉并报告错误:
import csv, sys
filename = 'some.csv'
with open(filename, 'rb') as f:
reader = csv.reader(f)
try:
for row in reader:
print row
except csv.Error as e:
sys.exit('file %s, line %d: %s' % (filename, reader.line_num, e))
,而该模块不能直接支持解析字符串,它可以很容易做到:
import csv
for row in csv.reader(['one,two,three']):
print row
Csv模块不直接支持读取和写入 unicode),但它是 8-位-清洁保存为 ASCII NUL 字符的一些问题。所以你可以写函数或类中处理的编码和解码为你,只要你避免像 UTF 16 使用 NULs 的编码。UTF-8 被建议。
下面的unicode_csv_reader()是一种生成器打包csv.reader处理 Unicode CSV 数据 (Unicode 字符串的列表)。 utf_8_encoder()是一种发电机,将 Unicode 字符串编码为 utf-8,一个字符串 (或行) 一次。CSV 读者分析编码的字符串和unicode_csv_reader()解码 UTF 8 编码细胞回 Unicode:
import csv
def unicode_csv_reader(unicode_csv_data, dialect=csv.excel, **kwargs):
# csv.py doesn't do Unicode; encode temporarily as UTF-8:
csv_reader = csv.reader(utf_8_encoder(unicode_csv_data),
dialect=dialect, **kwargs)
for row in csv_reader:
# decode UTF-8 back to Unicode, cell by cell:
yield [unicode(cell, 'utf-8') for cell in row]
def utf_8_encoder(unicode_csv_data):
for line in unicode_csv_data:
yield line.encode('utf-8')
对于所有其他编码可以使用下面的UnicodeReader和UnicodeWriter类。他们采取额外的编码参数在其构造函数中,并确保数据会通过真实的读者或作者为 utf-8 编码:
import csv, codecs, cStringIO
class UTF8Recoder:
"""
Iterator that reads an encoded stream and reencodes the input to UTF-8
"""
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("utf-8")
class UnicodeReader:
"""
A CSV reader which will iterate over lines in the CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
f = UTF8Recoder(f, encoding)
self.reader = csv.reader(f, dialect=dialect, **kwds)
def next(self):
row = self.reader.next()
return [unicode(s, "utf-8") for s in row]
def __iter__(self):
return self
class UnicodeWriter:
"""
A CSV writer which will write rows to CSV file "f",
which is encoded in the given encoding.
"""
def __init__(self, f, dialect=csv.excel, encoding="utf-8", **kwds):
# Redirect output to a queue
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
self.writer.writerow([s.encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = self.encoder.encode(data)
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)