>>> from env_helper import info; info()
页面更新时间: 2022-10-17 22:27:13
运行环境:
    Linux发行版本: Debian GNU/Linux 11 (bullseye)
    操作系统内核: Linux-5.10.0-18-amd64-x86_64-with-glibc2.31
    Python版本: 3.9.2

4.1. csv 模块

CSV 文件中的每行代表电子表格中的一行, 逗号分割了该行中的单元格。

我将使用这个文件作为本章的交互式环境的例子。 或在文本编辑器中输入文本,并保存为example.csvexample.csv 文件内容如下:

>>> !cat example.csv
4/5/2015 13:34,Apples,73
4/5/2015 3:41,Cherries,85
4/6/2015 12:46,Pears,14
4/8/2015 8:59,Oranges,52
4/10/2015 2:07,Apples,152
4/10/2015 18:10,Bananas,23
4/10/2015 2:40,Strawberries,98

CSV 文件是简单的,缺少Excel电子表格的许多功能。 例如, CSV 文件中:

  • 值没有类型,所有东西都是字符串;

  • 没有字体大小或颜色的设置;

  • 没有多个工作表;

  • 不能指定单元格的宽度和高度;

  • 不能合并单元格;

  • 不能嵌入图像或图表。

CSV的文件的优势是简单。CSV文件被许多种类的程序广泛地支持,可以在文本编辑器中查看(包括 IDLE的文件编辑器), 它是表示电子表格数据的直接方式。 CSV 格式和它声称的完全一致:它就是一个文本文件,具有逗号分隔的值。

因为CSV文件就是文本文件,所以你可能会尝试将它们读入一个字符串,然后处理这个字符串。 例如,因为 CSV 文件中的每个单元格有逗号分割,也许你可以只是对每行文本调用 split()方法,来取得这些值。 但并非 CSV 文件中的每个逗号,都表示两个单元格之间的分界。 CSV 文件也有自己的转义字符,允许逗号和其他字符作为值的一部分。 split() 方法不能处理这些转义字符。 因为这些潜在的缺陷,所以在 Python 中应该使用 csv 模块来读写CSV文件。

4.1.1. Reader 对象

要用 csv 模块从 CSV 文件中读取数据,需要创建一个 Reader 对象。 Reader 对象让你迭代遍历 CSV 文件 中的每一行。在交互式环境中输入以下代码,同时将 example.csv 放在当前工作目录中:

>>> import csv
>>> exampleFile = open('example.csv')
>>> exampleReader = csv.reader(exampleFile)
>>> exampleData = list(exampleReader)
>>> exampleData
[['4/5/2015 13:34', 'Apples', '73'],
 ['4/5/2015 3:41', 'Cherries', '85'],
 ['4/6/2015 12:46', 'Pears', '14'],
 ['4/8/2015 8:59', 'Oranges', '52'],
 ['4/10/2015 2:07', 'Apples', '152'],
 ['4/10/2015 18:10', 'Bananas', '23'],
 ['4/10/2015 2:40', 'Strawberries', '98']]

csv 模块是Python自带的,所以不需要安装就可以导入它。

要用 csv 模块读取CSV文件,首先用 open() 函数打开它,就像打开任何其他文本文件一样。但是, 不用在 open() 返回的 File 对象上调用 read()readlines() 方法,而是将它传递给 csv.reader() 函数。这将返回一个 Reader 对象, 供你使用。请注意,不能直接将文件名字符串传递给 csv.reader() 函数。

要访问 Reader 对象中的值,最直接的方法,就是 将它转换成一个普通Python列表,即将它传递给 list()。 在这个 Reader 对象上应用 list()函数, 将返回一个列表的列表。可以将它保存在变量 exampleData 中。在交互式环境中输入exampleData , 将显示列表的列表。

既然已经将 CSV 文件表示为列表的列表,就可以用 表达式 exampleData[row][col] 来访问特定行和列 的值。其中, rowexampleData 中一个 列表的下标,col 是该列表中你想访问的项的下标。 在交互式环境中输入以下代码:

>>> exampleData[0][0]
'4/5/2015 13:34'
>>> exampleData[0][1]
'Apples'
>>> exampleData[0][2]
'73'
>>> exampleData[1][1]
'Cherries'
>>> exampleData[6][1]
'Strawberries'

exampleData[0][0]进入第一个列表,并给出第一个 字符串。exampleData[0][2]进入第一个列表,并给 出第三个字符串,以此类推。

4.1.2. for 循环中,从 Reader 对象读取数据

对于大型的CSV文件,你需要在一个 for 循环中使用 Reader 对象。这样避免将整个文件一次性装入内存。 例如,在交互式环境中输入以下代码:

>>> import csv
>>> exampleFile = open ('example.csv')
>>> exampleReader = csv.reader(exampleFile)
>>> for row in exampleReader:
>>>     print('Row #' + str(exampleReader.line_num) + ' ' + str(row))
Row #1 ['4/5/2015 13:34', 'Apples', '73']
Row #2 ['4/5/2015 3:41', 'Cherries', '85']
Row #3 ['4/6/2015 12:46', 'Pears', '14']
Row #4 ['4/8/2015 8:59', 'Oranges', '52']
Row #5 ['4/10/2015 2:07', 'Apples', '152']
Row #6 ['4/10/2015 18:10', 'Bananas', '23']
Row #7 ['4/10/2015 2:40', 'Strawberries', '98']

在导入 csv 模块,并从CSV文件得到 Reader 对象 之后,可以循环遍历 Reader 对象中的行。每一行是 一个值的列表,每个值表示一个单元格。print() 函数 将打印出当前行的编号以及该行的内容。要取得行号,就 使用 Reader 对象的 line_num 变量,它包含了 当前行的编号。

Reader 对象只能循环遍历一次。要再次读取CSV文件, 必须调用 csv.reader ,创建一个对象。

4.1.3. Writer 对象

Writer 对象让你将数据写入CSV文件。要创建一个 Writer 对象,就使用csv.writer() 函数。 在交互式环境中输入以下代码。

>>> import csv
>>> outputFile = open('output.csv', 'w', newline='')
>>> outputWriter = csv.writer(outputFile)
>>> outputWriter.writerow(['spam', 'eggs', 'bacon', 'ham'])
21
>>> outputWriter.writerow(['Hello, world!', 'eggs', 'bacon', 'ham'])
32
>>> outputWriter.writerow([1, 2, 3.141592, 4])
16
>>> outputFile.close()

首先,调用 open() 并传入 'w',以写模式打开一个 文件。这将创建对象。然后将它传递给 csv.writer(), 创建一个Writer 对象。

在Windows上,需要为 open() 函数的 newline 关键字 参数传入一个空字符串。这样做的技术原因超出了本书的范围。 如果忘记设置 newline 关键字参数, output.csv 中的行距将有两倍。

Writer 对象的 writerow() 方法接受一个列表参数。 列表中的每个词,放在输出的CSV文件中的一个单元格中。 writerow() 函数的返回值,是写入文件中这一行的字符数(包括换行字符)。

这段代码生成的文件像下面这样:

spam,eggs,bacon,ham
"Hello, world!",eggs,bacon,ham
1,2,3.141592,4

请注意,Writer 对象自动转义'Hello, world!' 中的 逗号,在CSV文件中使用了双引号。模块 CSV 让你不必 自己处理这些特殊情况。

4.1.4. delimiterlineterminator 关键字参数

假定你希望用制表符代替逗号来分隔单元格, 并希望有两倍行距。可以在交互式环境中输 入下面这样的代码:

>>> import csv
>>> csvFile = open('example.tsv', 'w', newline='')
>>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n')
>>> csvWriter.writerow(['apples', 'oranges', 'grapes'])
23
>>> csvWriter.writerow(['eggs', 'bacon', 'ham'])
16
>>> csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam'])
31
>>> csvFile.close()

这改变了文件中的分隔符和行终止字符。分隔符是一行中单元格之间出现的字符。默认情况下, CSV文件的分隔符 是逗号。行终止字符是出现在行末的字符。默认情况下, 行终止字符是换行符。你可以利用 csv.writer()delimiterlineterminator关键字参数, 将这些字符改成不同的值。

传入 delimeter='\t'lineterminator='\n\n' , 这将单元格之间的字符改变为制表符,将行之间的字符 改变为两个换行符。然后我们调用 writerow() 三次, 得到3行。

这产生了文件 example.tsv ,包含以下内容:

>>> !more example.tsv
apples      oranges grapes

eggs        bacon   ham

spam        spam    spam    spam    spam    spam

既然单元格是由制表符分隔的,我们就使用文件扩展名.tsv,表示制表符分隔的值。