Python 文件及目录操作

在变量、序列和对象中存储的数据是暂时的,程序结束后就会丢失。为了能够长时间地保存程序中的数据,需要将程序中的数据保存到磁盘文件中。

10.1 基本文件操作
在Python中,内置了文件(File)对象。在使用文件对象时,首先需要通过内置的open()方法创建一个文件对象,然后通过该对象提供的方法进行一些基本文件操作。

10.1.1 创建和打开文件
在Python中,想要操作文件需要先创建或者打开指定的文件并创建文件对象,可以通过内置的open()函数实现。open()函数的基本语法格式如下:file = open(filename[,mode[,buffering]])
参数说明:

■ file:被创建的文件对象。

■ filename:要创建或打开文件的文件名称,需要使用单引号或双引号括起来。如果要打开的文件和当前文件在同一个目录下,那么直接写文件名即可,否则需要指定完整路径。例如,要打开当前路径下的名称为status.txt的文件,可以使用“status.txt”。

■ mode:可选参数,用于指定文件的打开模式,其参数值如表所示。默认的打开模式为只读(即r)。

 ■ buffering:可选参数,用于指定读写文件的缓冲模式,值为0表达式不缓存;值为1表示缓存;如果大于1,则表示缓冲区的大小。默认为缓存模式。
使用open()方法可以实现以下几个功能:
1.打开一个不存在的文件时先创建该文件
在默认的情况下,使用open()函数打开一个不存在的文件,会抛出异常。

Python 文件及目录操作_第1张图片

 ■ 在当前目录下(即与执行的文件相同的目录)创建一个名称为status.txt的文件。

■ 在调用open()函数时,指定mode的参数值为w、w+、a、a+。这样,当要打开的文件不存在时,就可以创建新的文件了。

实例创建并打开记录蚂蚁庄园动态的文件
在IDLE中创建一个名称为antmanor_message.py的文件,然后在该文件中,首先输出一条提示信息,然后再调用open()函数创建或打开文件,最后再输出一条提示信息,代码如下:

01 print("\n","="*10,"蚂蚁庄园动态","="*10)

02 file = open('message.txt','w') # 创建或打开保存蚂蚁庄园动态信息的文件

03 print("\n 即将显示……\n")
执行上面的代码,在antmaner_message.py文件所在的目录下创建一个名称为message.txt的文件,该文件没有任何内容。

2.以二进制形式打开文件
使用open()函数不仅可以以文本的形式打开文本文件,而且还可以以二进制形式打开非文本文件,如图片文件、音频文件、视频文件等。例如,创建一个名称为picture.png的图片文件,并且应用open()函数以二进制方式打开该文件。

以二进制方式打开该文件,并输出创建的对象的代码如下:file = open('picture.png','rb') # 以二进制方式打开图片文件print(file) # 输出创建的对象。

3.打开文件时指定编码方式
在使用open()函数打开文件时,默认采用GBK编码,当被打开的文件不是GBK编码时,将抛出异常。

解决该问题的方法有两种,一种是直接修改文件的编码,另一种是在打开文件时,直接指定使用的编码方式。

在调用open()函数时,通过添加encoding='utf-8'参数即可实现将编码指定为UTF-8。

例如,打开采用UTF-8编码保存的notice.txt文件,可以使用下面的代码:file = open('notice.txt','r',encoding='utf-8')

10.1.2 关闭文件
打开文件后,需要及时关闭,以免对文件造成不必要的破坏。关闭文件可以使用文件对象的close()方法实现。

close()方法的语法格式如下:

file.close()
其中,file为打开的文件对象。

说明:close()方法先刷新缓冲区中还没有写入的信息,然后再关闭文件,这样可以将没有写入到文件的内容写入到文件中。在关闭文件后,便不能再进行写入操作了。

10.1.3 打开文件时使用with语句
打开文件后,要及时将其关闭,如果忘记关闭可能会带来意想不到的问题。

为了更好地避免此类问题发生,可以使用Python提供的with语句,从而实现在处理文件时,无论是否抛出异常,都能保证with语句执行完毕后关闭已经打开的文件。with语句的基本语法格式如下:
with expression as target:    with-body
参数说明:

■ expression:用于指定一个表达式,这里可以是打开文件的open()函数。

■ target:用于指定一个变量,并且将expression的结果保存到该变量中。

■ with-body:用于指定with语句体,其中可以是执行with语句后相关的一些操作语句。如果不想执行任何语句,可以直接使用pass语句代替。

例如,将实例修改为在打开文件时使用with语句,修改后的代码如下:print("\n","="*10,"蚂蚁庄园动态","="*10)with open('message.txt','w') as file: # 创建或打开保存蚂蚁庄园动态信息的文件    passprint("\n 即将显示……\n")

10.1.4 写入文件内容
在实例01中,虽然创建并打开一个文件,但是该文件中并没有任何内容,它的大小是0KB。Python的文件对象提供了write()方法,可以向文件中写入内容。write()方法的语法格式如下:file.write(string)
其中,file为打开的文件对象;string为要写入的字符串。注意:在调用write()方法向文件中写入内容的前提是在打开文件时,指定的打开模式为w(可写)或者a(追加),否则,将抛出异常。

注意:在写入文件后,一定要调用close()方法关闭文件,否则写入的内容不会保存到文件中。这是因为当我们在写入文件内容时,操作系统不会立刻把数据写入磁盘,而是先缓存起来,只有调用close()方法时,操作系统才会保证把没有写入的数据全部写入磁盘。

多学两招:在Python的文件对象中除了提供了write()方法,还提供了writelines()方法,可以实现把字符串列表写入文件,但是不添加换行符。

10.1.5 读取文件
在Python中打开文件后,除了可以向其写入或追加内容,还可以读取文件中的内容。读取文件内容主要分为以下几种情况:
1.读取指定字符
文件对象提供了read()方法读取指定个数的字符,语法格式如下:

file.read([size])
参数说明:

■ file:为打开的文件对象。

■ size:可选参数,用于指定要读取的字符个数,如果省略,则一次性读取所有内容。

注意:在调用read()方法读取文件内容的前提是在打开文件时,指定的打开模式为r(只读)或者r+(读写),否则,将抛出的异常。

多学两招:在向文件中写入内容后,如果不想马上关闭文件,也可以调用文件对象提供的flush()方法,把缓冲区的内容写入文件,这样也能保证数据全部写入磁盘。

使用read(size)方法读取文件时,是从文件的开头读取的。如果想要读取部分内容,可以先使用文件对象的seek()方法将文件的指针移动到新的位置,然后再应用read(size)方法读取。seek()方法的基本语法格式如下:file.seek(offset[,whence])
参数说明:

■ file:表示已经打开的文件对象。

■ offset:用于指定移动的字符个数,其具体位置与whence参数有关。

■ whence:用于指定从什么位置开始计算。值为0表示从文件头开始计算,值为1表示从当前位置开始计算,值为2表示从文件尾开始计算,默认为0。注意:对于whence参数,如果在打开文件时,没有使用b模式(即rb),那么只允许从文件头开始计算相对位置,从文件尾计算时就会抛出异常。

说明:在使用seek()方法时,如果采用GBK编码,那么offset的值是按一个汉字(包括中文标点符号)占两个字符计算,而采用UTF-8编码,则一个汉字占3个字符,不过无论采用何种编码英文和数字都是按一个字符计算的。这与read(size)方法不同。

2.读取一行
在使用read()方法读取文件时,如果文件很大,一次读取全部内容到内存,容易造成内存不足,所以通常会采用逐行读取。文件对象提供了readline()方法用于每次读取一行数据。readline()方法的基本语法格式如下:file.readline()
其中,file为打开的文件对象。同read()方法一样,打开文件时,也需要指定打开模式为r(只读)或者r+(读写)。

3.读取全部行
读取全部行的作用同调用read()方法时不指定size类似,只不过读取全部行时,返回的是一个字符串列表,每个元素为文件的一行内容。读取全部行,使用的是文件对象的readlines()方法,其语法格式如下:file.readlines()
其中,file为打开的文件对象。同read()方法一样,打开文件时,也需要指定打开模式为r(只读)或者r+(读写)。

从该运行结果中可以看出readlines()方法的返回值为一个字符串列表。在这个字符串列表中,每个元素记录一行内容。如果文件比较大时,采用这种方法输出读取的文件内容会很慢。这时可以将列表的内容逐行输出。例如,下面的代码可以修改为以下内容。

print("\n","="*25,"蚂蚁庄园动态","="*25,"\n")

with open('message.txt','r') as file: # 打开保存蚂蚁庄园动态信息的文件    

messageall = file.readlines() # 读取全部动态信息  

 for message in messageall:        

print(message) # 输出一条动态信息

10.2 目录操作
目录也称文件夹,用于分层保存文件。通过目录可以分门别类地存放文件。我们也可以通过目录快速找到想要的文件。在Python中,并没有提供直接操作目录的函数或者对象,而是需要使用内置的os和os.path模块实现。

说明:os模块是Python内置的与操作系统功能和文件系统相关的模块。该模块中的语句的执行结果通常与操作系统有关,在不同操作系统上运行,可能会得到不一样的结果。

10.2.1 os和os.path模块
在Python中,内置了os模块及其子模块os.path用于对目录或文件进行操作。在使用os模块或者os.path模块时,需要先应用import语句将其导入,然后才可以应用它们提供的函数或者变量。
导入os模块可以使用下面的代码:import os说明:导入os模块后,也可以使用其子模块os.path。
导入os模块后,可以使用该模块提供的通用变量获取与系统有关的信息。常用的变量有以下几个:

■ name:用于获取操作系统类型。

■ linesep:用于获取当前操作系统上的换行符。

■ sep:用于获取当前操作系统所使用的路径分隔符。

os模块还提供了一些操作目录的函数,如表所示。

Python 文件及目录操作_第2张图片

 os.path模块也提供了一些操作目录的函数,如表所示。

Python 文件及目录操作_第3张图片

 10.2.2 路径
用于定位一个文件或者目录的字符串被称为一个路径。在程序开发时,通常涉及两种路径,一种是相对路径,另一种是绝对路径。
1.相对路径
在学习相对路径之前,需要先了解什么是当前工作目录。当前工作目录是指当前文件所在的目录。在Python中,可以通过os模块提供的getcwd()函数获取当前工作目录。例如,在E:\program\Python\Code\demo.py文件中,编写以下代码:import osprint(os.getcwd()) # 输出当前目录
执行上面的代码后,将显示以下目录,该路径就是当前工作目录。E:\program\Python\Code
相对路径就是依赖于当前工作目录的。如果在当前工作目录下,有一个名称为message.txt的文件,那么在打开这个文件时,就可以直接写上文件名,这时采用的就是相对路径,message.txt文件的实际路径就是当前工作目录“E:\program\Python\Code”+相对路径“message.txt”,即“E:\program\Python\Code\message.txt”。
如果在当前工作目录下,有一个子目录demo,并且在该子目录下保存着文件message.txt,那么在打开这个文件时就可以写上“demo/message.txt”,例如下面的代码:with open("demo/message.txt") as file: # 通过相对路径打开文件    pass说明:在Python中,指定文件路径时需要对路径分隔符“\”进行转义,即将路径中的“\”替换为“\\”。例如对于相对路径“demo\message.txt”需要使用“demo\\message.txt”代替。另外,也可以将路径分隔符“\”采用“/”代替。多学两招:在指定文件路径时,也可以在表示路径的字符串前面加上字母r(或R),那么该字符串将原样输出,这时路径中的分隔符就不需要再转义了。例如,上面的代码也可以修改为以下内容:with open(r"demo\message.txt") as file: # 通过相对路径打开文件    pass
2.绝对路径
绝对路径是指在使用文件时指定文件的实际路径。它不依赖于当前工作目录。在Python中,可以通过os.path模块提供的abspath()函数获取一个文件的绝对路径。abspath()函数的基本语法格式如下:os.path.abspath(path)
其中,path为要获取绝对路径的相对路径,可以是文件也可以是目录。
例如,要获取相对路径“demo\message.txt”的绝对路径,可以使用下面的代码:import osprint(os.path.abspath(r"demo\message.txt")) # 获取绝对路径
如果当前工作目录为“E:\program\Python\Code”,那么将得到以下结果:E:\program\Python\Code\demo\message.txt
3.拼接路径
如果想要将两个或者多个路径拼接到一起组成一个新的路径,可以使用os.path模块提供的join()函数实现。join()函数基本语法格式如下:os.path.join(path1[,path2[,……]])
其中,path1、path2用于代表要拼接的文件路径,这些路径间使用逗号进行分隔。如果在要拼接的路径中,没有一个绝对路径,那么最后拼接出来的将是一个相对路径。注意:使用os.path.join()函数拼接路径时,并不会检测该路径是否真实存在。
例如,需要将“E:\program\Python\Code”和“demo\message.txt”路径拼接到一起,可以使用下面的代码。import osprint(os.path.join("E:\program\Python\Code","demo\message.txt")) # 拼接字符串
执行上面的代码,将得到以下结果:E:\program\Python\Code\demo\message.txt说明:在使用join()函数时,如果要拼接的路径中,存在多个绝对路径,那么以从左到右为序最后一次出现的路径为准,并且该路径之前的参数都将被忽略。例如,执行下面的代码:import osprint(os.path.join("E:\\code","E:\\python\\mr","Code","C:\\","demo")) # 拼接字符串
将得到拼接后的路径为“C:\demo”。注意:把两个路径拼接为一个路径时,不要直接使用字符串拼接,而是使用os.path.join()函数,这样可以正确处理不同操作系统的路径分隔符。
10.2.3 判断目录是否存在
在Python中,有时需要判断给定的目录是否存在,这时可以使用os.path模块提供的exists()函数实现。exists()函数的基本语法格式如下:os.path.exists(path)
其中,path为要判断的目录,可以采用绝对路径,也可以采用相对路径。
返回值:如果给定的路径存在,则返回True,否则返回False。
例如,要判断绝对路径“C:\demo”是否存在,可以使用下面的代码:import osprint(os.path.exists("C:\\demo")) # 判断目录是否存在
执行上面的代码,如果在C盘根目录下没有demo子目录,则返回False,否则返回True。说明:os.path.exists()函数除了可以判断目录是否存在,还可以判断文件是否存在。例如,如果将上面代码中的“C:\\demo”替换为“C:\\demo\\test.txt”,则用于判断C:\demo\test.txt文件是否存在。
10.2.4 创建目录
在Python中,os模块提供了两个创建目录的函数,一个用于创建一级目录,另一个用于创建多级目录。
1.创建一级目录
创建一级目录是指一次只能创建一级目录。在Python中,可以使用os模块提供的mkdir()函数实现。通过该函数只能创建指定路径中的最后一级目录,如果该目录的上一级不存在,则抛出FileNotFoundError异常。mkdir()函数的基本语法格式如下:os.mkdir(path, mode=0o777)
参数说明:

■ path:用于指定要创建的目录,可以使用绝对路径,也可以使用相对路径。

■ mode:用于指定数值模式,默认值为0777。该参数在非UNIX系统上无效或被忽略。
例如,在Windows系统上创建一个C:\demo目录,可以使用下面的代码:import osos.mkdir("C:\\demo") # 创建C:\demo目录

注意:如果指定的目录有多级,而且最后一级的上级目录中有不存在的,则抛出FileNotFoundError异常,并且目录创建不成功。要解决该问题有两种方法,一种是使用创建多级目录的方法(将在后面进行介绍)。另一种是编写递归函数调用os.mkdir()函数实现,具体代码如下:

import os # 导入标准模块osdef mkdir(path): # 定义递归创建目录的函数  

 if not os.path.isdir(path): # 判断是否为有效路径        

mkdir(os.path.split(path)[0]) # 递归调用    else: # 如果目录存在,直接返回        

return    os.mkdir(path) # 创建目录

mkdir("D:/mr/test/demo") # 调用mkdir递归函数

2.创建多级目录
使用mkdir()函数只能创建一级目录,如果想创建多级目录,可以使用os模块提供的makedirs()函数,该函数用于采用递归的方式创建目录。makedirs()函数的基本语法格式如下:os.makedirs(name, mode=0o777)
参数说明:

■ name:用于指定要创建的目录,可以使用绝对路径,也可以使用相对路径。

■ mode:用于指定数值模式,默认值为0777。该参数在非UNIX系统上无效或被忽略。
例如,在Windows系统上,刚刚创建的C:\demo目录下,再创建子目录test\dir\mr(对应的目录为:C:\demo\test\dir\mr),可以使用下面的代码。import osos. makedirs ("C:\\demo\\test\\dir\\mr ") # 创建C:\demo\test\dir\mr目录

10.2.5 删除目录
删除目录可以通过使用os模块提供的rmdir()函数实现。通过rmdir()函数删除目录时,只有当要删除的目录为空时才起作用。rmdir()函数的基本语法格式如下:os.rmdir(path)
其中,path为要删除的目录,可以使用相对路径,也可以使用绝对路径。
例如,要删除刚刚创建的“C:\demo\test\dir\mr”目录,可以使用下面的代码:

import osos.rmdir("C:\\demo\\test\\dir\\mr") # 删除C:\demo\test\dir\mr目录
执行上面的代码后,将删除“C:\demo\test\dir”目录下的mr目录。

注意:如果要删除的目录不存在,那么将抛出“FileNotFoundError: [WinError 2] 系统找不到指定的文件”异常。因此,在执行os.rmdir()函数前,建议先判断该路径是否存在,可以使用os.path.exists()函数判断。具体代码如下:

import ospath = "C:\\demo\\test\\dir\\mr" # 指定要创建的目录

if os.path.exists(path): # 判断目录是否存在  

 os.rmdir("C:\\demo\\test\\dir\\mr") # 删除目录    

print("目录删除成功!")else:    print("该目录不存在!")

多学两招:使用rmdir()函数只能删除空的目录,如果想要删除非空目录,则需要使用Python内置的标准模块shutil的rmtree()函数实现。

例如,要删除不为空的“C:\\demo\\test”目录,可以使用下面的代码:import shutilshutil.rmtree("C:\\demo\\test") # 删除C:\demo目录下的test子目录及其内容

10.2.6 遍历目录
遍历在汉语中的意思是全部走遍,到处周游。在Python中,遍历是将指定的目录下的全部目录(包括子目录)及文件访问一遍。在Python中,os模块的walk()函数用于实现遍历目录的功能。walk()函数的基本语法格式如下:os.walk(top[, topdown][, onerror][, followlinks])
参数说明:

■ top:用于指定要遍历内容的根目录。

■ topdown:可选参数,用于指定遍历的顺序,如果值为True,表示自上而下遍历(即先遍历根目录);如果值为False,表示自下而上遍历(即先遍历最后一级子目录)。默认值为True。

■ onerror:可选参数,用于指定错误处理方式,默认为忽略,如果不想忽略也可以指定一个错误处理函数。通常情况下采用默认设置。

■ followlinks:可选参数,默认情况下,walk()函数不会向下转换成解析到目录的符号链接,将该参数值设置为True,表示用于指定在支持的系统上访问由符号链接指向的目录。

■ 返回值:返回一个包括3个元素(dirpath, dirnames, filenames)的元组生成器对象。其中,dirpath表示当前遍历的路径,是一个字符串;dirnames表示当前路径下包含的子目录,是一个列表;filenames表示当前路径下包含的文件,也是一个列表。
例如,要遍历指定目录“E:\program\Python\Code\01”,可以使用下面的代码:

import os # 导入os模块

tuples = os.walk("E:\\program\\Python\\Code\\01") # 遍历“E:\program\Python\Code\01”目录

for tuple1 in tuples: # 通过for循环输出遍历结果    

print(tuple1 ,"\n") # 输出每一级目录的元组

注意:walk()函数只在Unix系统和Windows系统中有效。

10.3 高级文件操作
Python内置的os模块除了可以对目录进行操作,还可以对文件进行一些高级操作,具体函数如表所示。

Python 文件及目录操作_第4张图片

 10.3.1 删除文件
Python没有内置删除文件的函数,但是在内置的os模块中提供了删除文件的函数remove(),该函数的基本语法格式如下:os.remove(path)
其中,path为要删除的文件路径,可以使用相对路径,也可以使用绝对路径。
例如,要删除当前工作目录下的mrsoft.txt文件,可以使用下面的代码:import os # 导入os模块os.remove("mrsoft.txt") # 删除当前工作目录下的mrsoft.txt文件
执行上面的代码后,如果在当前工作目录下存在mrsoft.txt文件,即可将其删除。

10.3.2 重命名文件和目录
os模块提供了重命名文件和目录的函数rename(),如果指定的路径是文件的,则重命名文件,如果指定的路径是目录,则重命名目录。rename()函数的基本语法格式如下:os.rename(src,dst)
其中,src用于指定要进行重命名的目录或文件;dst用于指定重命名后的目录或文件。
同删除文件一样,在进行文件或目录重命名时,如果指定的目录或文件不存在,也将抛出FileNotFoundError异常,所以在进行文件或目录重命名时,也建议先判断文件或目录是否存在,只有存在时才进行重命名操作。
例如,想要将“C:\demo\test\dir\mr\mrsoft.txt”文件重命名为“C:\demo\test\dir\mr\mr.txt”,可以使用下面的代码:

01 import os # 导入os模块

02 src = "C:\\demo\\test\\dir\\mr\\mrsoft.txt" # 要重命名的文件

03 dst = "C:\\demo\\test\\dir\\mr\\mr.txt" # 重命名后的文件

04 if os.path.exists(src): # 判断文件是否存在

05     os.rename(src,dst) # 重命名文件

06     print("文件重命名完毕!")

07 else:

08     print("文件不存在!")

使用rename()函数重命名目录与命名文件基本相同,只要把原来的文件路径替换为目录即可。例如,想要将当前目录下的demo目录重命名为test,可以使用下面的代码:

01 import os # 导入os模块

02 src = "demo" # 重命名的当前目录下的demo

03 dst = "test" # 重命名为test

04 if os.path.exists(src): # 判断目录是否存在

05     os.rename(src,dst) # 重命名目录

06     print("目录重命名完毕!")

07 else:

08     print("目录不存在!")

注意:在使用rename()函数重命名目录时,只能修改最后一级的目录名称。

10.3.3 获取文件基本信息
在计算机上创建文件后,该文件本身就会包含一些信息。例如,文件的最后一次访问时间、最后一次修改时间、文件大小等基本信息。通过os模块的stat()函数可以获取到文件的这些基本信息。stat()函数的基本语法如下:os.stat(path)
其中,path为要获取文件基本信息的文件路径,可以是相对路径,也可以是绝对路径。
stat()函数的返回值是一个对象,该对象包含如表所示的属性。通过访问这些属性可以获取文件的基本信息。

Python 文件及目录操作_第5张图片

 实例获取文件基本信息
在IDLE中创建一个名称为fileinfo.py的文件,首先在该文件中导入os模块,然后调用os模块的stat()函数获取文件的基本信息,最后输出文件的基本信息,代码如下:

01 import os # 导入os模块

02 fileinfo = os.stat("mr.png") # 获取文件的基本信息

03 print("文件完整路径:", os.path.abspath("mr.png")) # 获取文件的完整数路径

04 # 输出文件的基本信息

05 print("索引号:",fileinfo.st_ino)

06 print("设备名:",fileinfo.st_dev)

07 print("文件大小:",fileinfo.st_size," 字节")

08 print("最后一次访问时间:",fileinfo.st_atime)

09 print("最后一次修改时间:",fileinfo.st_mtime)

10 print("最后一次状态变化时间:",fileinfo.st_ctime)

10.5 小结
本章首先介绍了如何应用Python自带的函数进行基本文件操作,然后介绍了如何应用Python内置的os模块及其子模块os.path进行目录相关的操作,最后又介绍了如何应用os模块进行高级文件操作,例如删除文件、重命名文件和目录,以及获取文件基本信息等。

 

你可能感兴趣的:(python)