- 内容提要
- 作者简介
- 技术评审者简介
- 致谢
- 译者序 会编程的人不一样
- 前言
- 本书的读者对象
- 编码规范
- 什么是编程
- 本书简介
- 下载和安装 Python
- 启动 IDLE
- 如何寻求帮助
- 聪明地提出编程问题
- 小结
- 第一部分 Python 编程基础
- 第1章 Python 基础
- 第2章 控制流
- 第3章 函数
- 第4章 列表
- 第5章 字典和结构化数据
- 第6章 字符串操作
- 第二部分 自动化任务
- 第7章 模式匹配与正则表达式
- 第8章 读写文件
- 第9章 组织文件
- 第10章 调试
- 第11章 从 Web 抓取信息
- 第12章 处理 Excel 电子表格
- 第13章 处理 PDF 和 Word 文档
- 第14章 处理 CSV 文件和 JSON 数据
- 第15章 保持时间、计划任务和启动程序
- 第16章 发送电子邮件和短信
- 第17章 操作图像
- 第18章 用 GUI 自动化控制键盘和鼠标
- 附录A 安装第三方模块
- 附录B 运行程序
- 附录C 习题答案
14.1 csv 模块
CSV文件中的每行代表电子表格中的一行,逗号分割了该行中的单元格。例如,来自http://nostarch.com/automatestuff/的电子表格example.xlsx,在一个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
我将使用这个文件作为本章的交互式环境的例子。可以从http://nostarch.com/ automatestuff/下载example.csv,或在文本编辑器中输入文本,并保存为example.csv。
CSV文件是简单的,缺少Excel电子表格的许多功能。例如,CSV文件中:
· 值没有类型,所有东西都是字符串;
· 没有字体大小或颜色的设置;
· 没有多个工作表;
· 不能指定单元格的宽度和高度;
· 不能合并单元格;
· 不能嵌入图像或图表。
CSV的文件的优势是简单。CSV文件被许多种类的程序广泛地支持,可以在文本编辑器中查看(包括IDLE的文件编辑器),它是表示电子表格数据的直接方式。CSV格式和它声称的完全一致:它就是一个文本文件,具有逗号分隔的值。
因为CSV文件就是文本文件,所以你可能会尝试将它们读入一个字符串,然后用第8章中学到的技术处理这个字符串。例如,因为CSV文件中的每个单元格有逗号分割,也许你可以只是对每行文本调用split()方法,来取得这些值。但并非CSV文件中的每个逗号,都表示两个单元格之间的分界。CSV文件也有自己的转义字符,允许逗号和其他字符作为值的一部分。split()方法不能处理这些转义字符。因为这些潜在的缺陷,所以总是应该使用csv模块来读写CSV文件。
14.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]来访问特定行和列的值。其中,row是exampleData中一个列表的下标,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]进入第一个列表,并给出第三个字符串,以此类推。
14.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,创建一个对象。
14.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中的行距将有两倍,如图14-1所示。
图14-1 如果你在open()中忘记了newline=''关键字参数,CSV文件将有两倍行距
Writer对象的writerow()方法接受一个列表参数。列表中的每个词,放在输出的CSV文件中的一个单元格中。writerow()函数的返回值,是写入文件中这一行的字符数(包括换行字符)。
这段代码生成的文件像下面这样:
spam,eggs,bacon,ham "Hello, world!",eggs,bacon,ham 1,2,3.141592,4
请注意,Writer对象自动转义了'Hello, world!'中的逗号,在CSV文件中使用了双引号。模块csv让你不必自己处理这些特殊情况。
14.1.4 delimiter和lineterminator关键字参数
假定你希望用制表符代替逗号来分隔单元格,并希望有两倍行距。可以在交互式环境中输入下面这样的代码:
>>> import csv >>> csvFile = open('example.tsv', 'w', newline='') ❶ >>> csvWriter = csv.writer(csvFile, delimiter='\t', lineterminator='\n\n') >>> csvWriter.writerow(['apples', 'oranges', 'grapes']) 24 >>> csvWriter.writerow(['eggs', 'bacon', 'ham']) 17 >>> csvWriter.writerow(['spam', 'spam', 'spam', 'spam', 'spam', 'spam']) 32 >>> csvFile.close()
这改变了文件中的分隔符和行终止字符。分隔符是一行中单元格之间出现的字符。默认情况下,CSV文件的分隔符是逗号。行终止字符是出现在行末的字符。默认情况下,行终止字符是换行符。你可以利用csv.writer()的delimiter和lineterminator关键字参数,将这些字符改成不同的值。
传入delimeter='\t'和lineterminator='\n\n'❶,这将单元格之间的字符改变为制表符,将行之间的字符改变为两个换行符。然后我们调用writerow()三次,得到3行。
这产生了文件example.tsv,包含以下内容:
apples oranges grapes eggs bacon ham spam spam spam spam spam spam
既然单元格是由制表符分隔的,我们就使用文件扩展名.tsv,表示制表符分隔的值。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论