第九章 操作各类文件
本章中我们将学习操作各种文件类型,如PDF文件、Excel、CSV和txt文件。Python有对这些文件执行操作的不同模块。我们将学习如何使用Python来打开、编辑或从这些文件中读取数据。
本章将涉及如下课题:
- 操作PDF文件
- 操作Excel文件
- 操作CSV文件
- 操作txt文件
操作PDF文件
这一部分中,我们将学习如何使用Python模块来处理PDF文件。PDF是被广泛使用的一种文件格式,后缀名为.pdf。Python有一个名为PyPDF2的模块,有助于对pdf文件进行各类操作。它是一个第三方模块,是个创建为PDF工具集的Python库。
首先我们必须要安装该模块。要安装PyPDF2,在命令终端运行如下命令:
pip3 install PyPDF2
下面我们来看其中的一些操作来处理PDF文件,比如读取PDF,获取页面数,提取文本和旋转 PDF 页面。
读取PDF文档并获取页数
这部分中我们将学习使用PyPDF2模块来读取PDF文件。同时我们会获取到PDF的页面数。该模块带有一个名为PdfFileReader()的函数可进行PDF文件的读取。确保系统里有一个PDF文件。这里我们在系统里有一个Haltermanpythonbook.pdf文件,因此在这一部分中都会使用该文件。使用你的PDF文件名来替换Haltermanpythonbook.pdf。创建脚本read_pdf.py并编写如下内容:
import PyPDF2
with open('Haltermanpythonbook.pdf', 'rb') as pdf:
read_pdf = PyPDF2.PdfFileReader(pdf)
print("Number of pages in pdf : ", read_pdf.numPages)
运行脚本将得到如下输出:
$ python3 read_pdf.py
# 输出结果
Number of pages in pdf : 283
上例中,我们使用了PyPDF2模块。然后我们创建了一个pdf文件对象。PdfFileReader() 会读取所创建的对象。在读取PDF文件后,我们使用numPages属性来获取PDF文件的页数。本例中为283页。
提取文本
要提取PDF文件的页面内容,PyPDF2模块带有一个extractText()方法。创建一个名为extract_text.py的脚本并编写如下内容:
import PyPDF2
with open('Haltermanpythonbook.pdf', 'rb') as pdf:
read_pdf = PyPDF2.PdfFileReader(pdf)
pdf_page = read_pdf.getPage(2)
pdf_content = pdf_page.extractText()
print(pdf_content)
运行脚本可得到如下输出:
$ python3 extract_text.py
# 输出结果
i
Contents
1TheContextofSoftwareDevelopment1
1.1Software............................................
2
1.2DevelopmentTools......................................
2
1.3LearningProgrammingwithPython.............................
4
1.4WritingaPythonProgram..................................
5
1.5ALongerPythonprogram..................................
8
1.6Summary...........................................
9
1.7Exercises...........................................
9
2ValuesandVariables11
2.1IntegerValues.........................................
11
2.2VariablesandAssignment...................................
16
2.3...........................................
19
2.4Floating-pointTypes.....................................
23
2.5ControlCodeswithinStrings.................................
24
2.6UserInput...........................................
26
2.7The
eval
Function......................................
27
2.8Controllingthe
print
Function................................
29
2.9Summary...........................................
31
2.10Exercises...........................................
32
3ExpressionsandArithmetic35
3.1Expressions..........................................
35
3.2OperatorPrecedenceandAssociativity............................
40
3.3Comments...........................................
41
3.4Errors.............................................
42
©2011RichardL.Halterman
Draftdate:November13,2011
上例中我们创建了一个文件读取器对象。pdf读取器对象有一个名为getPage()的函数,可接收页面数(索引从0开始)来作为参数,并返回页面对象。然后我们使用了extractText()方法,它可提取getPage()中所指定的的页面的文本。页面的索引从0开始。
旋转PDF页面
这部分中我们来看看如何对PDF页面进行旋转。我们可以使用PDF对象的rotate.Clockwise()来进行实现。创建一个名为rotate_pdf.py的脚本并编写如下内容:
import PyPDF2
with open('Haltermanpythonbook.pdf', 'rb') as pdf:
rd_pdf = PyPDF2.PdfFileReader(pdf)
wr_pdf = PyPDF2. PdfFileWriter()
for pg_num in range(rd_pdf.numPages):
pdf_page = rd_pdf.getPage(pg_num)
pdf_page.rotateClockwise(90)
wr_pdf.addPage(pdf_page)
with open('rotated.pdf', 'wb') as pdf_out:
wr_pdf.write(pdf_out)
print("pdf successfully rotated")
运行脚本将得到如下输出:
$ python3 rotate_pdf.py
# 输出结果
pdf successfully rotated
上例中为实现pdf的旋转,我们首先创建一个原pdf文件的pdf文件读取器。然后将旋转后的页面写入一个新的pdf文件中。对新pdf文件的定性主,我们使用了PyPDF2模块中的PdfFileWriter()函数。新的pdf文件以rotated.pdf名称进行保存。这时我们使用rotateClockwise()方法来旋转pdf文件的页面。然后,使用addPage()方法,来添加旋转后的页面。接着我们将这些pdf页面写入新的pdf文件。因此,首先我们应打开新的文件对象 (pdf_out)并使用pdf的写入器对象的write()方法来写入 pdf页面。最后,我们将关闭原文件对象(Haltermanpythonbook.pdf)以及新的文件对象(pdf_out)。
操作Excel文件
这一部分我们来学习后缀名为.xlsx的Excel文件的处理。这一后缀名是一种Microsoft Excel使用的OpenXML 数据表文件格式。
Python有多个模块可处理Excel文件:xlrd , pandas和openpyxl。这一部分中我们将学习使用这三个模块来处理Excel文件。
首先我们会来看一个使用xlrd模块的示例。xlrd模块用于读取、写入和修改Excel数据表以及其它相关处理。
使用xlrd模块
首先我们要安装xlrd模块。在终端中运行如下命令来安装xlrd模块:
pip3 install xlrd
ℹ️注意:要确保系统里有Excel文件。我这里系统中有一个sample.xlsx文件。在这一部分中我都会使用该文件。
译者注: Alan 使用了一个网上可下载的示例 Excel文件:Sample - Superstore.xls
我们来看如何读取Excel文件以及如何从Excel文件中提取行和列。
读取Excel文件
这一部分中,我们来看下如何读取Excel文件。我们需要用到 xlrds模块,创建一个脚本read_excel.py并编写如下内容:
import xlrd
excel_file = (r"Sample - Superstore.xls")
book_obj = xlrd.open_workbook(excel_file)
excel_sheet = book_obj.sheet_by_index(0)
result = excel_sheet.cell_value(0, 1)
print(result)
运行脚本将得到如下输出:
$ python3 read_excel.py
# 输出结果:
Order ID
上例中,我们导入了xlrd模块来读取Excel文件。我们还传入了Excel文件的位置。然后,创建了一个文件对象,传入了索引值,这样就从会索引处开始读取。最后我们打印出了结果。
提取列名
这一部分我们来从Excel表格中提取列名。创建一个名为extract_column_names.py的脚本并编写如下内容:
import xlrd
excel_file = ('Sample - Superstore.xls')
book_obj = xlrd.open_workbook(excel_file)
excel_sheet = book_obj.sheet_by_index(0)
excel_sheet.cell_value(0,0)
for i in range(excel_sheet.ncols):
print(excel_sheet.cell_value(0,i))
运行脚本,我们将得到如下输出:
$ python3 extract_column_names.py
# 输出结果:
Row ID
Order ID
Order Date
Ship Date
Ship Mode
Customer ID
Customer Name
Segment
Country
City
State
Postal Code
Region
Product ID
Category
Sub-Category
Product Name
Sales
Quantity
Discount
Profit
上例中,我们从Excel表章中提取了列名。我们使用ncols属性获取了列名。
使用pandas
在使用Pandas读取Excel文件之前,我们首先要安装pandas模块。我们可通过下面的命令安装pandas:
pip3 install pandas
ℹ️注意:确保在你的系统里有一个Excel文件。我的系统里有一个sample.xlsx。因此在整个部分中我将使用该文件。
译者注: Alan 将继续使用前文下载的文件
下面我们来看看使用pandas的一些示例。
读取Excel文件
这一部分中,我们将使用pandas模块来读取Excel文件。下面我们来看一个读取Excel文件的示例。
创建一个名为 rd_excel_pandas.py的文件并编写如下内容:
import pandas as pd
excel_file = 'Sample - Superstore.xls'
df = pd.read_excel(excel_file)
print(df.head())
运行以上脚本将得到如下输出:
$ python3 rd_excel_pandas.py
# 输出结果
Row ID Order ID Order Date ... Quantity Discount Profit
0 1 CA-2016-152156 2016-11-08 ... 2 0.00 41.9136
1 2 CA-2016-152156 2016-11-08 ... 3 0.00 219.5820
2 3 CA-2016-138688 2016-06-12 ... 2 0.00 6.8714
3 4 US-2015-108966 2015-10-11 ... 5 0.45 -383.0310
4 5 US-2015-108966 2015-10-11 ... 2 0.20 2.5164
[5 rows x 21 columns]
上例中,我们使用了pandas来读取Excel文件。首先我们导入了pandas模块。然后我们创建了一个excel_file字符串来存储打开的文件名,以供pandas做进一步的操作。再后我们创建了一个数据帧对象df。在该例中,我们使用了pandas的read_excel方法来以默认函数从Excel文件中读取数据。读取从索引0处开始。最后,我们打印出了pandas数据帧。
读取Excel文件指定列
在使用pandas模块并通过read_excel方法读取Excel文件时,我们还能够读取该文件中的列名。要读取指定的列名,我们需要在read_excel方法中使用usecols参数。
下面我们来看一个读取Excel文件指定列的示例。创建一个名为rd_excel_pandas1.py的脚本并编写如下内容:
import pandas as panda
excel_file = 'Sample - Superstore.xls'
cols = [1, 2, 3]
df = panda.read_excel(excel_file, sheet_names='Orders', usecols=cols)
print(df.head())
运行上述脚本将得到如下输出:
$ python3 rd_excel_pandas1.py
# 输出结果:
Order ID Order Date Ship Date
0 CA-2016-152156 2016-11-08 2016-11-11
1 CA-2016-152156 2016-11-08 2016-11-11
2 CA-2016-138688 2016-06-12 2016-06-16
3 US-2015-108966 2015-10-11 2015-10-18
4 US-2015-108966 2015-10-11 2015-10-18
上例中首先我们导入了pandas模块。然后我们创建一个名为excel_file的字符串来存储文件名。再后我们定义了变量cols并传入其中列的索引值。这样在使用read_excel方法时,在该方法内,我们还传入了usecols参数来通过索引获取前面通过变量cols定义的指定列。因此,在运行脚本后,我们从Excel文件中获取的仅为指定列。
我们还可以使用pandas模块进行各种其它操作,比如读取有缺失数据的Excel文件、跳过指定行以及读取多个Excel表单。
使用openpyxl
openpyxl是一个用于读取和写入xlsx, xlsm, xltx和xltm文件的Python库。首先,我们要安装openpyxl。运行如下命令:
pip3 install openpyxl
下面我们将使用openpyxl来看一些示例。
新建Excel文件
这一部分中,我们将学习使用openpyxl来创建一个新的Excel文件。创建一个名为create_excel.py的脚本并编写如下内容:
from openpyxl import Workbook
book_obj = Workbook()
excel_sheet = book_obj.active
excel_sheet['A1'] = 'Name'
excel_sheet['A2'] = 'student'
excel_sheet['B1'] = 'age'
excel_sheet['B2'] = '24'
book_obj.save("test.xlsx")
print("Excel created successfully")
运行脚本,我们将得到如下输出:
$ python3 create_excel.py
# 输出结果:
Excel created successfully
这时查看当前的工作目录,就可以看到成功地创建了test.xlsx。在上例中,我们向单元格中写入了数据。然后在openpyxl模块中我们导入了Workbook类。工作簿(workbook)是文档其它部分的容器。接着我们我们为活跃表单设置了引用对象,并在A1, A2和B1, B2单元中写入了值。最后,我们通过save() 方法向test.xlsx文件写入了内容。
追加值
这一部分中,我们将在Excel中追加值。这时就要使用到append() 方法。我们可以在想要添加值的当前表单底部添加一组值。创建一个名为append_values.py的脚本并编写如下内容:
from openpyxl import Workbook
book_obj = Workbook()
excel_sheet = book_obj.active
rows = (
(11, 12, 13),
(21, 22, 23),
(31, 32, 33),
(41, 42, 43)
)
for values in rows:
excel_sheet.append(values)
print()
print("values are successfully appended")
book_obj.save('test.xlsx')
运行脚本将得到如下输出:
$ python3 append_values.py
# 输出结果
values are successfully appended
上例中,我们在test.xlsx文件表单中追加了三列数据。数据以元组内的元组进行存储,通过容器逐行追加数据并使用append()方法插入数据。
读取多个单元格
这一部分中我们将学习读取多个单元格。我们将使用openpyxl模块。创建一个名为read_multiple.py的脚本并编写如下内容:
import openpyxl
book_obj = openpyxl.load_workbook('Sample - Superstore.xlsx')
excel_sheet = book_obj.active
cells = excel_sheet['A1':'C6']
for c1, c2, c3 in cells:
print("{0:6} {1:6} {2}".format(c1.value, c2.value, c3.value))
运行脚本将得到如下输出:
$ python3 read_multiple.py
# 输出结果
Row ID Order ID Order Date
1 CA-2016-152156 2016-11-08 00:00:00
2 CA-2016-152156 2016-11-08 00:00:00
3 CA-2016-138688 2016-06-12 00:00:00
4 US-2015-108966 2015-10-11 00:00:00
5 US-2015-108966 2015-10-11 00:00:00
译者注: 需将前述的 xls 文件转化为 xlsx 格式,因 openpyxl 不支持老版本的格式
前例中,我们通过使用范围运算读取了三列的数据。然后读取 A1 – C6单元格之间的数据。
类似地,我们还可以使用openpyxl模块来对Excel文件进行其它大量操作,如合并单元格、拆分单元格。
操作CSV文件
CSV格式表示逗号分隔值(Comma Separated Value)。逗号用于分隔一条记录的各个字段。常用于数据表和数据库中导入导出该格式。
CSV是一种使用特定结构类型排列表格数据的普通文本文件。Python有一个内置的csv模块,由Python来解析这类文件。csv模块多可用于处理从数据表和数据库中导出的带有字段和记录的文本格式文件。
csvs模块内置所有需用到的函数,如下:
- csv.reader: 该函数用于返回一个reader对象,可遍历CSV文件各行
- csv.writer: 该函数用于返回一个writer对象,可向CSV文件写入数据
- csv.register_dialect: 该函数用于注册一个CSV dialect
- csv.unregister_dialect: 该函数用于取消一个CSV dialect的注册
- csv.get_dialect: 该函数用于返回一个给定名称的dialect
- csv.list_dialects: 该函数用于返回所有注册的dialect
- csv.field_size_limit: 该函数用于返回当前解析器所允许的最大字段数
这一部分中,我们仅会来学习csv.reader和csv.writer。
读取CSV文件
Python带有一个内置模块csv,我们将使用它来处理CSV文件。我们会使用csv.reader模块来读取CSV文件。创建一个名为csv_read.py的脚本并编写如下内容:
import csv
csv_file = open('Sample - Superstore.csv', 'r', encoding='windows-1252')
with csv_file:
read_csv = csv.reader(csv_file)
#for row in read_csv:
#print(row)
for index, row in enumerate(read_csv):
if index <= 5:
print(row)
译者注: Alan 使用相同的文件转成了 CSV 格式,运行中出现了报错UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xa0 in position 2928: invalid start byte,添加了 encoding方能解决,这与 Mac 和 Windows对 CSV 的处理方式相关。同时因原表数据较多,这里修改为仅打印5行数据。
运行脚本,我们将得到如下输出:
$ python3 csv_read.py
#输出结果:
['Row ID;Order ID;Order Date;Ship Date;Ship Mode;Customer ID;Customer Name;Segment;Country;City;State;Postal Code;Region;Product ID;Category;Sub-Category;Product Name;Sales;Quantity;Discount;Profit']
['1;CA-2016-152156;2016/11/8;2016/11/11;Second Class;CG-12520;Claire Gute;Consumer;United States;Henderson;Kentucky;42420;South;FUR-BO-10001798;Furniture;Bookcases;Bush Somerset Collection Bookcase;261.96;2;0;41.9136']
['2;CA-2016-152156;2016/11/8;2016/11/11;Second Class;CG-12520;Claire Gute;Consumer;United States;Henderson;Kentucky;42420;South;FUR-CH-10000454;Furniture;Chairs;Hon Deluxe Fabric Upholstered Stacking Chairs', ' Rounded Back;731.94;3;0;219.582']
['3;CA-2016-138688;2016/6/12;2016/6/16;Second Class;DV-13045;Darrin Van Huff;Corporate;United States;Los Angeles;California;90036;West;OFF-LA-10000240;Office Supplies;Labels;Self-Adhesive Address Labels for Typewriters by Universal;14.62;2;0;6.8714']
["4;US-2015-108966;2015/10/11;2015/10/18;Standard Class;SO-20335;Sean O'Donnell;Consumer;United States;Fort Lauderdale;Florida;33311;South;FUR-TA-10000577;Furniture;Tables;Bretford CR4500 Series Slim Rectangular Table;957.5775;5;0.45;-383.031"]
["5;US-2015-108966;2015/10/11;2015/10/18;Standard Class;SO-20335;Sean O'Donnell;Consumer;United States;Fort Lauderdale;Florida;33311;South;OFF-ST-10000760;Office Supplies;Storage;Eldon Fold 'N Roll Cart System;22.368;2;0.2;2.5164"]
前面的程序中,我们将Sample - Superstore.csv文件打开为csv_file。然后,我们使用了csv.reader()函数来将数据提取到读取器对象,我们可以对该对象进行迭代来获取数据的每一行。下面,我们来看第二个函数csv.Writer()。
写入CSV文件
要将数据写入csv文件,我们使用csv.writer模块。这一部分中,我们将存储一些数据到Python列表中,然后将该数据放到csv文件中。创建一个名为csv_write.py的脚本并编写如下内容:
import csv
write_csv = [['Name', 'Sport'], ['Andres Iniesta', 'Footbal'], ['AB de Villiers', 'Cricket'], ['Vira Kohli', 'Cricket'], ['Lionel Messi', 'Football']]
with open('csv_write.csv', 'w') as csvFile:
writer = csv.writer(csvFile)
writer.writerows(write_csv)
print(write_csv)
运行脚本,我们将得到如下输出:
$ python3 csv_write.py
# 输出结果:
[['Name', 'Sport'], ['Andres Iniesta', 'Footbal'], ['AB de Villiers', 'Cricket'], ['Vira Kohli', 'Cricket'], ['Lionel Messi', 'Football']]
以上程序中,我们创建了一个包含姓名和对应运动项目的名为write_csv的列表。接着在创建列表后,我们打开了新创建的csv_write.csvy文件并使用csv.writer() 函数将write_csv列表插入到该文件中。
操作txt文件
普通文本文件用于存储仅表示字符或字符串的数据,并且不包含任何结构化的元数据。Python中无需导入任何外部库来读取和写入文本文件。Python提供了内置的函数来创建、打开、关闭、写入和读取文本文件。要进行这些操作,有不同的访问模式来对打开的文件处理可用的操作。
Python中这些访问模式如下:
- 只读模式 (‘r’):该模式以只读打开文本文件。如果该文件不存在,则抛出一个 I/O错误。我们也可称这种模式为打开文件的默认模式。
- 读写模式(‘r+’): 该模式以读写打开文本文件,如果该文件不存在,则抛出一个 I/O错误。
- 只写模式(‘w’): 该模式打开文本文件来进行写入。在文件不存在时则创建文件,对已存在的文件则覆盖原数据。
- 写读模式(‘w+’): 该模式会打开文本文件来进行读取和写入。对已存在的文件会覆盖原数据。
- 追加模式 (‘a’): 该模式会打开文本文件来进行写入。如果文件不存在则会创建文件,数据会在已有数据的最后进行插入。
- 追加读取模式(‘a+’): 该模式会打开文本文件进行读取和客户。如果文件不存在则会创建文件,数据会在已有数据的最后进行插入。
open()函数
该函数用于打开文件,不需要导入任何外部模块。
语法如下:
Name_of_file_object = open("文件名","访问模式")
对于上述的语法,文件必须要在Python程序相同的目录下。如果文件不在相同目录下,那么我们还需要定义打开文件时的文件路径。这类情况的语法如下所示:
Name_of_file_object = open("/home/……/文件名","访问模式")
打开文件
这里使用open函数打开文件"test.txt"。该文本来相同目录下,并以追加模式打开:
text_file = open("test.txt","a")
如果文件不在同级目录。我们需在追加模式下定义路径:
text_file = open("/home/…../test.txt","a")
close()函数
该函数用于关闭文件,它会释放文件所占用的内存。在无需再使用文件或以不同模式打开文件时使用该函数。
语法如下:
Name_of_file_object.close()
以下代码可用来简单地打开和关闭一个文件:
# 打开并关闭test.txt:
text_file = open("test.txt","a")
text_file.close()
写入文本文件
通过使用Python,我们可以创建一个文本文件(test.txt)。通过代码向文件本文件写入非常容易。打开一个文件进行写入,我们将第二个访问模式参数设为"w"。要向test.txt文件写入数据,我们使用文件句柄对象的write()方法。创建一个名为text_write.py的脚本并编写如下内容:
text_file = open("test.txt", "w")
text_file.write("Monday\nTuesday\nWednesday\nThursday\nFriday\nSaturday\n")
text_file.close()
运行以上脚本将会进行文件的创建。这时查看当前工作目录。我们可以发现所创建的test.txt文件。查看文件的内容,我们会发现write()函数写入的星期保存在了test.txt中。
上面的程序中,我们声明了变量text_file来打开名为test.txt.的文件。open函数中传入两个参数:第一个为要打开文件,第二个为表示要对文件进行或应用的权限和操作的访问模式。在程序中,我们在第二参数中使用了字母"w",即写入模式。然后,我们使用了text_file.close()来关闭存储的test.txt文件实例。
读取文本文件
读取文件和写入文件一样简单。要以读取打开一个文件,我们使用"r"代替"w"来作为第二个参数设置访问模式。要从该文件读取数据,我们使用该文件句柄对象的read()方法。创建一个名为text_read.py的脚本并编写如下内容:
text_file = open("test.txt", "r")
data = text_file.read()
print(data)
text_file.close()
输出如下:
$ python3 text_read.py
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
在以上程序中,我们定义了一个变量text_file来打开文件test.txt。open函数接收两个参数:第一个为要打开的文件,,第二个为表示要对文件进行或应用的权限和操作的访问模式。在程序中,我们使用了字母"r"作为第二个参数,表示写入操作。然后我们使用了text_file.close()来关闭存储文件test.txt的实例。在运行Python程序之后,我们可以轻易地在终端中查看这一文本文件的内容。
总结
本章中,我们学习了各类文件的操作,包括PDF, Excel, CSV和文本文件。我们使用了Python的各模块来执行这类型文件的部分操作。
下一章中,我们将学习Python中的基础网络和因特网模块。
课后问题
- readline()和readlines()之间的区别是什么?
- open()和with open()之间的区别是什么?
- 开头的r c:\Downloads意义何在?
- 什么是生成器对象?
- pass的用处是什么?
- lambda表达式是什么?
扩展阅读
- XLRD: https://xlrd.readthedocs.io/en/latest/api.html
- openoyxl: http://www.python-excel.org/
- 生成器函数的概念: https://wiki.python.org/moin/Generators