前言

CSV (Comma Separated Values) 格式是电子表格和数据库中最常见的输入、输出文件格式。

csv 模块实现了 CSV 格式表单数据的读写。其提供了诸如“以兼容 Excel 的方式输出数据文件”或“读取 Excel 程序输出的数据文件”的功能,程序员无需知道 Excel 所采用 CSV 格式的细节。此模块同样可以用于定义其他应用程序可用的 CSV 格式或定义特定需求的 CSV 格式。

csv 模块中的 reader 类和 writer 类可用于读写序列化的数据。也可使用 DictReader 类和 DictWriter 类以字典的形式读写数据。

本文只介绍 csv 模块的常用函数。

原教程链接: https://docs.python.org/zh-cn/3/library/csv.html .

操作系统:Windows 10 专业版

参考文档

  1. csv — CSV 文件读写

模块内容

csv 模块定义了以下函数:

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

返回一个 reader 对象,该对象将逐行遍历 csvfile。csvfile 可以是任何对象,只要这个对象支持 iterator 协议并在每次调用 __next__() 方法时都返回字符串,文件对象 和列表对象均适用。如果 csvfile 是文件对象,则打开它时应使用 newline=‘’。

csv 文件的每一行都读取为一个由字符串组成的列表。除非指定了 QUOTE_NONNUMERIC 格式选项(在这种情况下,未加引号的字段会转换为浮点数),否则不会执行自动数据类型转换。

一个简短的用法示例:

1
2
3
4
5
6
7
>>> 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=‘’。为了尽量简化与实现 DB API 的模块之间的接口,None 值会被当作空字符串写入。虽然这个转换是不可逆的,但它可以简化 SQL NULL 数据值到 CSV 文件的转储而无需预处理从 cursor.fetch* 调用返回的数据。在被写入之前所有其他非字符串数据都会先用 str() 来转转为字符串。

一个简短的用法示例:

1
2
3
4
5
6
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 模块定义了以下类:

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

创建一个对象,该对象在操作上类似于常规 reader,但是将每行中的信息映射到一个 dict,该 dict 的键由 fieldnames 可选参数给出。

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

如果某一行中的字段多于字段名,则剩余数据会被放入一个列表,并与 restkey 所指定的字段名 (默认为 None) 一起保存。 如果某个非空白行的字段少于字段名,则缺失的值会使用 restval 的值来填充 (默认为 None)。

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

一个简短的用法示例:

1
2
3
4
5
6
7
8
9
10
11
>>> 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)

创建一个对象,该对象在操作上类似常规 writer,但会将字典映射到输出行。 fieldnames 参数是由键组成的 序列,它指定字典中值的顺序,这些值会按指定顺序传递给 writerow() 方法并写入文件 f。 如果字典缺少 fieldnames 中的键,则可选参数 restval 用于指定要写入的值。 如果传递给 writerow() 方法的字典的某些键在 fieldnames 中找不到,则可选参数 extrasaction 用于指定要执行的操作。 如果将其设置为默认值 ‘raise’,则会引发 ValueError。 如果将其设置为 ‘ignore’,则字典中的其他键值将被忽略。 所有其他可选或关键字参数都传递给底层的 writer 实例。

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

一个简短的用法示例:

1
2
3
4
5
6
7
8
9
10
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'})

Reader 对象

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

  • csvreader.__next__()

返回 reader 的可迭代对象的下一行,它可以是一个列表(如果对象是由 reader() 返回)或字典(如果是一个 DictReader 实例),根据当前 Dialect 来解析。 通常你应当以 next(reader) 的形式来调用它。

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

  • csvreader.dialect

变种描述,只读,供解析器使用。

  • csvreader.line_num

源迭代器已经读取了的行数。它与返回的记录数不同,因为记录可能跨越多行。

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

  • DictReader.fieldnames

字段名称。如果在创建对象时未传入字段名称,则首次访问时或从文件中读取第一条记录时会初始化此属性。

Writer 对象

Writer 对象(DictWriter 实例和 writer() 函数返回的对象)具有下面的公开方法。对于 Writer 对象,行 必须是(一组可迭代的)字符串或数字。对于 DictWriter 对象,行 必须是一个字典,这个字典将字段名映射为字符串或数字(数字要先经过 str() 转换类型)。请注意,输出的复数会有括号包围。这样其他程序读取 CSV 文件时可能会有一些问题(假设它们完全支持复数)。

  • csvwriter.writerow(row)

将 row 形参写入到 writer 的文件对象,根据当前 Dialect 进行格式化。 返回对下层文件对象的 write 方法的调用的返回值。

  • csvwriter.writerows(rows)

将 rows*(即能迭代出多个上述 *row 对象的迭代器)中的所有元素写入 writer 的文件对象,并根据当前设置的变种进行格式化。

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

  • csvwriter.dialect

变种描述,只读,供 writer 使用。

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

  • DictWriter.writeheader()

在 writer 的文件对象中,写入一行字段名称(字段名称在构造函数中指定),并根据当前设置的变种进行格式化。本方法的返回值就是内部使用的 csvwriter.writerow() 方法的返回值。

例子

读取 CSV 文件最简单的一个例子:

1
2
3
4
5
import csv
with open('some.csv', newline='') as f:
reader = csv.reader(f)
for row in reader:
print(row)

读取其他格式的文件:

1
2
3
4
5
import csv
with open('passwd', newline='') as f:
reader = csv.reader(f, delimiter=':', quoting=csv.QUOTE_NONE)
for row in reader:
print(row)

相应最简单的写入示例是:

1
2
3
4
import csv
with open('some.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerows(someiterable)

Since open() is used to open a CSV file for reading, the file will by default be decoded into unicode using the system default encoding (see locale.getencoding()). To decode a file using a different encoding, use the encoding argument of open:

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

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

Reader 的更高级用法——捕获并报告错误:

1
2
3
4
5
6
7
8
9
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))

尽管该模块不直接支持解析字符串,但仍可如下轻松完成:

1
2
3
4
5
6
>>> import csv
>>> for row in csv.reader(['one,two,three']):
... print(row)
...
['one', 'two', 'three']
>>>

结语

第五十五篇博文写完,开心!!!!

今天,也是充满希望的一天。