第8章 读写文件
当程序运行时,变量是保存数据的好方法,但如果希望程序结束后数据仍然保持,就需要将数据保存到文件中。你可以认为文件的内容是一个字符串值,大小可能有几个GB。在本章中,你将学习如何使用Python在硬盘上创建、读取和保存文件。
文件与文件路径
文件有两个关键属性:“文件名”(通常写成一个单词)和“路径”。路径指明了文件在计算机上的位置。文件名中,最后一个句点之后的部分称为文件的“扩展名”,它指出了文件的类型。文件夹可以包含文件和其他文件夹。路径中的C:\部分是“跟文件夹”,它包含了所有其他文件夹。在OS X 和Linux中,根文件夹是/。附加卷,诸如DVD驱动器或者USB闪存驱动器,在不同的操作系统上显示也不同。虽然文件夹名称和文件名在Windows和OS X上是不区分大小写的,但在Linux上是区分大小写的。
Windows上的倒斜杠以及OS X和Linux上的正斜杠
在Windows上,路径书写使用倒斜杠作为文件夹之间的分隔符。但在OS X和Linux上,使用正斜杠作为它们的路径分隔符。如果想要程序运行在所有操作系统上,在编写Python脚本时,就必须处理这两种情况。好在,用os.path.join()函数来做这件事很简单。如果将单个文件和路径上的文件夹名称的字符串传递给它,os.path.join()就会返回一个文件路径的字符串,包含正确的路径分隔符。例:
import os
os.path.join('usr','bin','span')
out:'usr\\bin\\spam'(注意:倒斜杠有两个,因为每个倒斜杠需要由另一个倒斜杠字符来转义)。
如果需要创建文件名称的字符串,os.path.join()函数就很有用。这些字符串将传递给几个文件相关的函数,本章将进行介绍。
当前工作目录
每个运行在计算机上的程序,都有一个“当前工作目录”,或swd。所有没有从根文件夹开始的文件名或路径,都假定在当前工作目录下。利用os.getcwd()函数,可以取得当前工作路径的字符串,并可以利用os.chdir()改变它。如果要更改的当前工作目录不存在,Python就会显示一个错误。
注意:虽然文件夹是目录的更新的名称,但请注意,当前工作目录(或当前目录)是标准术语,没有当前工作文件夹这种说法。
绝对路径与相对路径
有两种方法指定一个文件路径。
* “绝对路径”,总是从根文件开始。
* “相对路径”,它相对于程序的当前工作目录。
还有点(.)和点点(..)文件夹。它们不是真正的文件夹,而是可以在路径中使用的特殊名称。单个的句点(“点”)用作文件夹目名称时,是“这个目录”的缩写。两个句点(“点点”)意思是父文件夹。相对路径开始处的.\是可选的。例如,.\spam.txt和spam.txt指的是同一个文件。
用os.makedirs()创建新文件夹
程序可以用os.makedirs()函数创建新文件夹(目录)。例
import os
os.makedirs('c:\\delicious\\walnut\\waffles')
os.makedirs()将创建所有必要的中间文件夹,目的是确保完整路径名存在。
os.path模块
os.path模块包含了许多与文件名和路径相关的有用函数。因为os.path是os模块中的模块,所以只要执行import os就可以导入它。os.path模块的完整文档在Python网站上:http://docs.python.org/3/library/os.path.html。
处理绝对路径和相对路径
os.path模块提供了一些函数,返回一个相对路径的绝对路径,以及检查给定的路径是否为绝对路径。
# 调用os.path.abspath(path)将返回参数的绝对路径的字符串。这就是将相对路径转换为绝对路径的简便方法。
# 调用os.path.isabs(path),如果参数是一个绝对路径,就返回True,如果参数是一个相对路径,就返回False。
# 调用os.path.relpath(path,start)将返回从start路径到path的相对路径的字符串。如果没有提供start,就使用当前工作目录作为开始路径。
注意:因为在你的系统上,文件和文件夹可能与我的不同,所以你不能完全遵照本章中的每一个例子,但还是请尝试用你的计算机上存在的文件夹来完成例子。
调用os.path.dirname(path)将返回一个字符串,它包含path参数中最后一个斜杠之前的所有内容。调用os.path.basename(path)将返回一个字符串,它包含path参数中最后一个斜杠之后的所有内容。如果同时需要一个路径的目录名称和基本名称,就可以调用os.path.split(),获得这两个字符串的元组。请注意,可以调用os.path.dirname()和os.path.basename(),将它们的返回值放在一个元组中,从而得到同样的元组。同时也请注意,os.path.split()不会接受一个文件路径并返回每个文件夹的字符串的列表。如果需要这样,请使用split()字符串方法,并根据os.path.sep中的字符串进行分割。例:
calcFilePath = 'C:\\Windows\\System32\\calc.exe'
calcFilePath.split(os.path.sep)
out:['C:','Windows','System32','calc.exe']
在OS X和Linux系统上,返回的列表头上有一个空字符串:
'/usr/bin'.split(os.path.sep)
out:['','usr','bin']
split()字符串方法将返回一个列表,包含该路径的所有部分。如果向它传递os.path.sep,就能在所有操作系统上工作。
查看文件大小和文件夹内容
一旦有办法处理文件路径,就可以开始搜集特定文件和文件夹的信息。os.path模块提供了一些函数,用于查看文件的字节数以及给定文件夹中的文件和子文件夹。
# 调用os.path.getsize(path)将返回path参数中文件的字节数。
# 调用os.listdir(path)将返回文件名字符串的列表,包含path参数中的每个文件。如果想知道这个目录下所有文件的总字节数,就可以同时使用os.path.getsize()和os.listdir()。
检查路径有效性
如果你提供的路径不存在,许多Python函数就会崩溃并报错。os.path模块提供了一些函数,用于检测给定的路径是否存在,以及它是文件还是文件夹。
# 如果path参数所指的文件或文件夹存在,调用os.path.exists(path)将返回True,否则返回False。
# 如果path参数存在,并且是一个文件,调用os.path.isfile(path)将返回True,否则返回False。
# 如果path参数存在,并且是一个文件夹,调用os.path.isdir(path)将返回True,否则返回False。
利用os.path.exists()函数,可以确定DVD或闪存盘当前是否连接在计算机上。
文件读写过程
“二进制文件”是所有其他文件类型,诸如字处理文档、PDF、图像、电子表格和可执行程序。如果用Notepad或TextEdit打开一个二进制文件,它看起来就像乱码。既然每种不同类型的二进制文件,都必须用它自己的方式来处理。在Python中,读写文件有3个步骤:
1.调用open()函数,返回一个File对象。
2.调用File对象的read()或write()方法。
3.调用File对象的close()方法,关闭该文件。
用open()函数打开文件
要用open()函数打开一个文件,就要向它传递一个字符串路径,表明希望打开的文件。这既可以是绝对路径,也可以是相对路径。open()函数返回一个File对象。例:helloFile=open('C:\\Users\\your_home_folder\\hello.txt')这些命令都将以读取纯文本文件的模式打开文件,或简称为“读模式”。当文件以读模式打开时,Python只让你从文件中读取数据,你不能以任何方式写入或修改它。在Python中打开文件时,读模式是默认的模式。但如果你不希望依赖于Python的默认值,也可以明确指明该模式,向open()传入字符串'r',作为第二个参数。所以open('/User/aweigart/hello.txt','r')和open('/User/aweigart/hello.txt')做的事情一样。调用open()函数将返回一个File对象。File对象代表计算机中的一个文件,它只是Python中另一种类型的值,就像你已熟悉的列表和字典。当你需要读取或写入该文件,就可以调用helloFile变量中的File对象的方法。
读取文件内容
既然有了一个File对象,就可以开始从它读取内容。如果你希望将整个文件的内容读取为一个字符串值,就使用File对象的read()方法。例:helloContent = helloFile.read() 如果你将文件的内容看成是单个大字符串,read()方法就返回保存在该文件中的这个字符串。或者,可以使用readlines()方法,从该文件取得一个字符串的列表。列表中的每个字符串就是文本中的每一行。请注意,每个字符串值都以一个换行字符\n结束。除了文件的最后一行。与点歌大字符串相比,字符串的列表通常更容易处理。
写入文件
Python允许你将内容写入文件,方式与print()函数将字符串“写”到屏幕上类似。但是,如果打开文件时用读模式,就不能写入文件。你需要以“写入纯文本模式”或“添加纯文本模式”打开该文件,或简称为“写模式”和“添加模式”。写模式将覆盖原有的文件,从头开始,将'w'作为第二个参数传递给open(),以写模式打开该文件。不同的是,添加模式将在已有文件的末尾添加文本。将'a'作为第二个参数传递给open(),以添加模式都会创建一个新的空文件。在读取或写入文件后,调用close()方法,然后才能再次打开该文件。请注意,write()方法不会像print()函数那样,在字符串添加的末尾自动添加换行字符。必须自己该字符。
用shelve模块保存变量
利用shelve模块,你可以将Python程序中的变量保存到二进制的shelf文件中。这样,程序就可以从硬盘中恢复变量的数据。shelve模块让你在程序中添加“保存”和“打开”功能。例如,如果运行一个程序,并输入了一些配置设置,就可以将这些设置保存到一个shelf文件,然后让程序下一次运行时加载它们。
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zophie','Pooka','Simon']
shelfFile['cats'] = cats
shelfFile.close()
要利用shelve模块读写数据,首先要导入它。调用函数shelve.open()并传入一个文件名,然后将返回的值保存在一个变量中。可以对这个变量的shelf值进行修改,就像它是一个字典一样。当你完成时,在这个值上调用close()。在Windows上运行前面的代码,你会看到在当前工作目录下有3个新文件:mydata.bak、mydata.dat和mydata.dir。在OS X上,只会创建一个mydata.db文件。这些二进制文件包含了存储在shelf中的数据。你的程序稍后可以使用shelve模块,重新打开这些文件并取出数据。shelf值不必用读模式或写模式打开,因为它们在打开后,既能读又能写。就像字典一样,shelf值有keys()和values()方法,返回shelf中键和值的类似列表的值。因为这些方法返回类似列表的值,而不是真正的列表,所以应该将它们传递给list()函数,取得列表的形式。例:
shelfFile = shelve.open('mydata')
list(shelfFile.keys())
out:['cats']
list(shelfFile.values())
out:[['Zophie','Pooka','Simon']]
shelfFile.close()
创建文件时,如果你需要在Notepad或TextEdit这样的文本编辑器中读取它们,纯文本就非常有用。但是,如果想要保存Python程序中的数据,那就使用shelve模块。
用pprint.pformat()函数保存变量
假定你有一个字典,保存在一个变量中,你希望保存这个变量和它的内容,以便将来使用。pprint.pformat()函数将提供一个字符串,你可以将它写入.py文件。该文件将成为你自己的模块,如果你需要使用存储在其中的变量,就导入它。import语句导入的模块本身就是Python脚本。如果来自pprint.pformat()的字符串保存为一个.py文件,该文件就是一个可以导入的模块,就像其他模块一样。由于Python脚本本身也是带有.py文件扩展名的文本文件,所以你的Python程序甚至可以生成其他Python程序。然后可以将这些文件导入到脚本中。
创建一个.py文件(而不是利用shelve模块保存变量)的好处在于,因为它是一个文本文件,所以任何人都可以用一个简单的文本编辑器读取和修改该文件的内容。但是,对于大多数应用,利用shelve模块来保存数据,是将变量保存到文件的最佳方式。只有基本数据类型,诸如整型、浮点型、字符串、列表和字典,可以作为简单文本写入一个文件。例如,File对象就不能够编码为文本。
项目:生成随机的测试试卷文件
项目:多重剪贴板
(第八章完)
当程序运行时,变量是保存数据的好方法,但如果希望程序结束后数据仍然保持,就需要将数据保存到文件中。你可以认为文件的内容是一个字符串值,大小可能有几个GB。在本章中,你将学习如何使用Python在硬盘上创建、读取和保存文件。
文件与文件路径
文件有两个关键属性:“文件名”(通常写成一个单词)和“路径”。路径指明了文件在计算机上的位置。文件名中,最后一个句点之后的部分称为文件的“扩展名”,它指出了文件的类型。文件夹可以包含文件和其他文件夹。路径中的C:\部分是“跟文件夹”,它包含了所有其他文件夹。在OS X 和Linux中,根文件夹是/。附加卷,诸如DVD驱动器或者USB闪存驱动器,在不同的操作系统上显示也不同。虽然文件夹名称和文件名在Windows和OS X上是不区分大小写的,但在Linux上是区分大小写的。
Windows上的倒斜杠以及OS X和Linux上的正斜杠
在Windows上,路径书写使用倒斜杠作为文件夹之间的分隔符。但在OS X和Linux上,使用正斜杠作为它们的路径分隔符。如果想要程序运行在所有操作系统上,在编写Python脚本时,就必须处理这两种情况。好在,用os.path.join()函数来做这件事很简单。如果将单个文件和路径上的文件夹名称的字符串传递给它,os.path.join()就会返回一个文件路径的字符串,包含正确的路径分隔符。例:
import os
os.path.join('usr','bin','span')
out:'usr\\bin\\spam'(注意:倒斜杠有两个,因为每个倒斜杠需要由另一个倒斜杠字符来转义)。
如果需要创建文件名称的字符串,os.path.join()函数就很有用。这些字符串将传递给几个文件相关的函数,本章将进行介绍。
当前工作目录
每个运行在计算机上的程序,都有一个“当前工作目录”,或swd。所有没有从根文件夹开始的文件名或路径,都假定在当前工作目录下。利用os.getcwd()函数,可以取得当前工作路径的字符串,并可以利用os.chdir()改变它。如果要更改的当前工作目录不存在,Python就会显示一个错误。
注意:虽然文件夹是目录的更新的名称,但请注意,当前工作目录(或当前目录)是标准术语,没有当前工作文件夹这种说法。
绝对路径与相对路径
有两种方法指定一个文件路径。
* “绝对路径”,总是从根文件开始。
* “相对路径”,它相对于程序的当前工作目录。
还有点(.)和点点(..)文件夹。它们不是真正的文件夹,而是可以在路径中使用的特殊名称。单个的句点(“点”)用作文件夹目名称时,是“这个目录”的缩写。两个句点(“点点”)意思是父文件夹。相对路径开始处的.\是可选的。例如,.\spam.txt和spam.txt指的是同一个文件。
用os.makedirs()创建新文件夹
程序可以用os.makedirs()函数创建新文件夹(目录)。例
import os
os.makedirs('c:\\delicious\\walnut\\waffles')
os.makedirs()将创建所有必要的中间文件夹,目的是确保完整路径名存在。
os.path模块
os.path模块包含了许多与文件名和路径相关的有用函数。因为os.path是os模块中的模块,所以只要执行import os就可以导入它。os.path模块的完整文档在Python网站上:http://docs.python.org/3/library/os.path.html。
处理绝对路径和相对路径
os.path模块提供了一些函数,返回一个相对路径的绝对路径,以及检查给定的路径是否为绝对路径。
# 调用os.path.abspath(path)将返回参数的绝对路径的字符串。这就是将相对路径转换为绝对路径的简便方法。
# 调用os.path.isabs(path),如果参数是一个绝对路径,就返回True,如果参数是一个相对路径,就返回False。
# 调用os.path.relpath(path,start)将返回从start路径到path的相对路径的字符串。如果没有提供start,就使用当前工作目录作为开始路径。
注意:因为在你的系统上,文件和文件夹可能与我的不同,所以你不能完全遵照本章中的每一个例子,但还是请尝试用你的计算机上存在的文件夹来完成例子。
调用os.path.dirname(path)将返回一个字符串,它包含path参数中最后一个斜杠之前的所有内容。调用os.path.basename(path)将返回一个字符串,它包含path参数中最后一个斜杠之后的所有内容。如果同时需要一个路径的目录名称和基本名称,就可以调用os.path.split(),获得这两个字符串的元组。请注意,可以调用os.path.dirname()和os.path.basename(),将它们的返回值放在一个元组中,从而得到同样的元组。同时也请注意,os.path.split()不会接受一个文件路径并返回每个文件夹的字符串的列表。如果需要这样,请使用split()字符串方法,并根据os.path.sep中的字符串进行分割。例:
calcFilePath = 'C:\\Windows\\System32\\calc.exe'
calcFilePath.split(os.path.sep)
out:['C:','Windows','System32','calc.exe']
在OS X和Linux系统上,返回的列表头上有一个空字符串:
'/usr/bin'.split(os.path.sep)
out:['','usr','bin']
split()字符串方法将返回一个列表,包含该路径的所有部分。如果向它传递os.path.sep,就能在所有操作系统上工作。
查看文件大小和文件夹内容
一旦有办法处理文件路径,就可以开始搜集特定文件和文件夹的信息。os.path模块提供了一些函数,用于查看文件的字节数以及给定文件夹中的文件和子文件夹。
# 调用os.path.getsize(path)将返回path参数中文件的字节数。
# 调用os.listdir(path)将返回文件名字符串的列表,包含path参数中的每个文件。如果想知道这个目录下所有文件的总字节数,就可以同时使用os.path.getsize()和os.listdir()。
检查路径有效性
如果你提供的路径不存在,许多Python函数就会崩溃并报错。os.path模块提供了一些函数,用于检测给定的路径是否存在,以及它是文件还是文件夹。
# 如果path参数所指的文件或文件夹存在,调用os.path.exists(path)将返回True,否则返回False。
# 如果path参数存在,并且是一个文件,调用os.path.isfile(path)将返回True,否则返回False。
# 如果path参数存在,并且是一个文件夹,调用os.path.isdir(path)将返回True,否则返回False。
利用os.path.exists()函数,可以确定DVD或闪存盘当前是否连接在计算机上。
文件读写过程
“二进制文件”是所有其他文件类型,诸如字处理文档、PDF、图像、电子表格和可执行程序。如果用Notepad或TextEdit打开一个二进制文件,它看起来就像乱码。既然每种不同类型的二进制文件,都必须用它自己的方式来处理。在Python中,读写文件有3个步骤:
1.调用open()函数,返回一个File对象。
2.调用File对象的read()或write()方法。
3.调用File对象的close()方法,关闭该文件。
用open()函数打开文件
要用open()函数打开一个文件,就要向它传递一个字符串路径,表明希望打开的文件。这既可以是绝对路径,也可以是相对路径。open()函数返回一个File对象。例:helloFile=open('C:\\Users\\your_home_folder\\hello.txt')这些命令都将以读取纯文本文件的模式打开文件,或简称为“读模式”。当文件以读模式打开时,Python只让你从文件中读取数据,你不能以任何方式写入或修改它。在Python中打开文件时,读模式是默认的模式。但如果你不希望依赖于Python的默认值,也可以明确指明该模式,向open()传入字符串'r',作为第二个参数。所以open('/User/aweigart/hello.txt','r')和open('/User/aweigart/hello.txt')做的事情一样。调用open()函数将返回一个File对象。File对象代表计算机中的一个文件,它只是Python中另一种类型的值,就像你已熟悉的列表和字典。当你需要读取或写入该文件,就可以调用helloFile变量中的File对象的方法。
读取文件内容
既然有了一个File对象,就可以开始从它读取内容。如果你希望将整个文件的内容读取为一个字符串值,就使用File对象的read()方法。例:helloContent = helloFile.read() 如果你将文件的内容看成是单个大字符串,read()方法就返回保存在该文件中的这个字符串。或者,可以使用readlines()方法,从该文件取得一个字符串的列表。列表中的每个字符串就是文本中的每一行。请注意,每个字符串值都以一个换行字符\n结束。除了文件的最后一行。与点歌大字符串相比,字符串的列表通常更容易处理。
写入文件
Python允许你将内容写入文件,方式与print()函数将字符串“写”到屏幕上类似。但是,如果打开文件时用读模式,就不能写入文件。你需要以“写入纯文本模式”或“添加纯文本模式”打开该文件,或简称为“写模式”和“添加模式”。写模式将覆盖原有的文件,从头开始,将'w'作为第二个参数传递给open(),以写模式打开该文件。不同的是,添加模式将在已有文件的末尾添加文本。将'a'作为第二个参数传递给open(),以添加模式都会创建一个新的空文件。在读取或写入文件后,调用close()方法,然后才能再次打开该文件。请注意,write()方法不会像print()函数那样,在字符串添加的末尾自动添加换行字符。必须自己该字符。
用shelve模块保存变量
利用shelve模块,你可以将Python程序中的变量保存到二进制的shelf文件中。这样,程序就可以从硬盘中恢复变量的数据。shelve模块让你在程序中添加“保存”和“打开”功能。例如,如果运行一个程序,并输入了一些配置设置,就可以将这些设置保存到一个shelf文件,然后让程序下一次运行时加载它们。
import shelve
shelfFile = shelve.open('mydata')
cats = ['Zophie','Pooka','Simon']
shelfFile['cats'] = cats
shelfFile.close()
要利用shelve模块读写数据,首先要导入它。调用函数shelve.open()并传入一个文件名,然后将返回的值保存在一个变量中。可以对这个变量的shelf值进行修改,就像它是一个字典一样。当你完成时,在这个值上调用close()。在Windows上运行前面的代码,你会看到在当前工作目录下有3个新文件:mydata.bak、mydata.dat和mydata.dir。在OS X上,只会创建一个mydata.db文件。这些二进制文件包含了存储在shelf中的数据。你的程序稍后可以使用shelve模块,重新打开这些文件并取出数据。shelf值不必用读模式或写模式打开,因为它们在打开后,既能读又能写。就像字典一样,shelf值有keys()和values()方法,返回shelf中键和值的类似列表的值。因为这些方法返回类似列表的值,而不是真正的列表,所以应该将它们传递给list()函数,取得列表的形式。例:
shelfFile = shelve.open('mydata')
list(shelfFile.keys())
out:['cats']
list(shelfFile.values())
out:[['Zophie','Pooka','Simon']]
shelfFile.close()
创建文件时,如果你需要在Notepad或TextEdit这样的文本编辑器中读取它们,纯文本就非常有用。但是,如果想要保存Python程序中的数据,那就使用shelve模块。
用pprint.pformat()函数保存变量
假定你有一个字典,保存在一个变量中,你希望保存这个变量和它的内容,以便将来使用。pprint.pformat()函数将提供一个字符串,你可以将它写入.py文件。该文件将成为你自己的模块,如果你需要使用存储在其中的变量,就导入它。import语句导入的模块本身就是Python脚本。如果来自pprint.pformat()的字符串保存为一个.py文件,该文件就是一个可以导入的模块,就像其他模块一样。由于Python脚本本身也是带有.py文件扩展名的文本文件,所以你的Python程序甚至可以生成其他Python程序。然后可以将这些文件导入到脚本中。
创建一个.py文件(而不是利用shelve模块保存变量)的好处在于,因为它是一个文本文件,所以任何人都可以用一个简单的文本编辑器读取和修改该文件的内容。但是,对于大多数应用,利用shelve模块来保存数据,是将变量保存到文件的最佳方式。只有基本数据类型,诸如整型、浮点型、字符串、列表和字典,可以作为简单文本写入一个文件。例如,File对象就不能够编码为文本。
项目:生成随机的测试试卷文件
项目:多重剪贴板
(第八章完)