购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.2 文件夹和文件操作

掌握了pathlib模块的路径操作,就可以通过构造好的路径对象对文件夹或文件执行实际操作了,如文件夹或文件的新建、删除、重命名、状态信息获取等。本节就来讲解相关的知识。

1.2.1 exists()函数——判断文件夹或文件是否存在

路径对象的exists()函数用于判断一个路径指向的文件夹或文件是否存在,如果存在则返回True,如果不存在则返回False。其语法格式如下:

表达式.exists()

参数说明:

表达式:一个路径对象。

具体到实际应用,在程序中常常需要将生成的文件保存到指定文件夹下,如果该文件夹不存在,就会报错。为避免手动创建文件夹的麻烦,可先用exists()函数进行判断,再根据判断结果执行创建文件夹的指令。此外,在程序中保存文件时,为避免新文件覆盖已有文件导致数据丢失,也可先用exists()函数进行判断,再根据判断结果做相应的处理,从而提高程序的安全性。

应用场景 判断指定的文件夹和文件是否存在

◎代码文件:exists()函数.py

本案例要使用exists()函数判断文件夹“F:\python\第1章”是否存在,并判断该文件夹中是否存在工作簿“供应商信息表.xlsx”和“供应商.xlsx”,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p1 = Path('F:\\python\\第1章') # 给出文件夹的路径
3 p2 = p1 / '供应商信息表.xlsx' # 给出第1个工作簿的路径
4 p3 = p1 / '供应商.xlsx' # 给出第2个工作簿的路径
5 print(p1.exists()) # 判断文件夹是否存在
6 print(p2.exists()) # 判断第1个工作簿是否存在
7 print(p3.exists()) # 判断第2个工作簿是否存在

代码运行结果如下:


1 True
2 True
3 False

由运行结果可知,文件夹“F:\python\第1章”是存在的,该文件夹中有名为“供应商信息表.xlsx”的工作簿,但没有名为“供应商.xlsx”的工作簿。

1.2.2 is_dir()函数和is_file()函数——判断路径指向的对象是文件夹还是文件

路径对象的is_dir()函数和is_file()函数分别用于判断路径指向的对象是否为文件夹或文件。如果路径指向的对象是文件夹或文件,函数返回True,否则返回False。此外,如果路径指向的对象不存在,函数会返回False。

这两个函数的语法格式如下:

表达式.is_dir/is_file()

参数说明:

表达式:一个路径对象。

应用场景 判断路径指向的对象是文件夹还是文件

◎代码文件:is_dir()函数和is_file()函数.py

假设计算机硬盘上有如右图所示的文件夹和文件,下面使用is_dir()函数和is_file()函数分别进行判断,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p1 = Path('F:\\python\\第1章\\工作信息表') # 指定第1个路径
3 p2 = Path('F:\\python\\第1章\\供应商信息表.xlsx') # 指定第2个路径
4 print(p1.is_dir()) # 判断第1个路径指向的对象是否为文件夹
5 print(p1.is_file()) # 判断第1个路径指向的对象是否为文件
6 print(p2.is_dir()) # 判断第2个路径指向的对象是否为文件夹
7 print(p2.is_file()) # 判断第2个路径指向的对象是否为文件

代码运行结果如下,可以看到,函数的判断结果与路径的实际情况相符。


1 True
2 False
3 False
4 True

1.2.3 mkdir()函数和rmdir()函数——新建和删除文件夹

路径对象的mkdir()函数用于按照指定的路径新建文件夹。其语法格式如下:

表达式.mkdir(parents,exist_ok)

参数说明:

表达式:一个路径对象,指向要新建的文件夹。

parents:当参数值为False或者省略该参数时,如果找不到要新建的文件夹的上一级路径,会报错,提示系统找不到指定的路径;当参数值为True时,则会自动新建任何不存在的上级路径。

exist_ok:如果要新建的文件夹已存在,当参数值为False或者省略该参数时,会报错,提示文件夹已存在,无法新建;当参数值为True时,则不会报错。

路径对象的rmdir()函数用于按照指定的路径删除文件夹(必须为空文件夹,否则会报错)。其语法格式如下:

表达式.rmdir()

参数说明:

表达式:一个路径对象,指向要删除的文件夹。

应用场景1 在指定文件夹中新建一个文件夹

◎代码文件:mkdir()函数.py

假设计算机硬盘上已有文件夹“F:\python”,本案例要使用mkdir()函数在该文件夹中新建一个文件夹“test”,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python') # 指定新建文件夹的上一级路径
3 p1 = p / 'test' # 构建新建文件夹的完整路径
4 p1.mkdir(parents=False, exist_ok=True) # 根据构建的路径新建文件夹

运行以上代码后,即可在文件夹“F:\python”中看到新建的文件夹“test”,如右图所示。

应用场景2 删除指定的空文件夹

◎代码文件:rmdir()函数.py

本案例要使用rmdir()函数删除文件夹“F:\python\第1章”下的空文件夹“信息表”,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\信息表') # 指定要删除的空文件夹的路径
3 p.rmdir() # 根据指定的路径删除空文件夹

运行以上代码后,文件夹“F:\python\第1章”下的空文件夹“信息表”就被删除了。

1.2.4 touch()函数和unlink()函数——新建和删除文件

路径对象的touch()函数用于按照指定的路径新建空白文件。其语法格式如下:

表达式.touch(exist_ok)

参数说明:

表达式:一个路径对象,指向要新建的文件。

exist_ok:如果路径指向的文件已存在,当参数值为False或者省略该参数时会报错;当参数值为True时不会报错,并且文件的修改时间会被更新为当前时间,文件的内容不变。

路径对象的unlink()函数用于按照指定的路径删除文件。其语法格式如下:

表达式.unlink(missing_ok)

参数说明:

表达式:一个路径对象,指向要删除的文件。

missing_ok(Python 3.8及以上版本可用):如果路径指向的文件不存在,当参数值为False或者省略该参数时会报错,当参数值为True时则不报错。

需要注意的是,由于用unlink()函数删除的文件难以恢复,在实际工作中使用该函数时一定要谨慎,以免因误删文件导致数据丢失。

应用场景1 在指定文件夹中新建csv文件

◎代码文件:touch()函数.py

本案例要使用touch()函数在文件夹“F:\python”中新建一个文件“员工信息表.csv”,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\员工信息表.csv') # 指定新建文件的路径
3 p.touch(exist_ok=False) # 根据路径新建文件

应用场景2 删除指定文件夹中的工作簿

◎代码文件:unlink()函数.py

◎数据文件:库存表.xlsx

本案例要使用unlink()函数删除文件夹“F:\python\第1章”中的工作簿“库存表.xlsx”,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\库存表.xlsx') # 指定要删除的工作簿的路径
3 p.unlink() # 根据路径删除工作簿

1.2.5 rename()函数和replace()函数——重命名或移动文件夹和文件

路径对象的rename()函数和replace()函数作用相同,都可以重命名或移动文件夹和文件,也就是说可以修改文件夹和文件的名称和存放位置。这两个函数的语法格式如下:

表达式.rename/replace(target)

参数说明:

表达式:一个路径对象,指向要重命名或移动的文件夹或文件。

target:指定文件夹或文件重命名或移动后的新路径,可以为路径对象或路径字符串。如果该参数指向的文件夹或文件已存在,rename()函数会报错,而replace()函数则会直接覆盖。

需要注意的是,这两个函数都只能在同一个磁盘分区中进行操作,否则会报错。

应用场景 将工作簿重命名并移动到其他文件夹

◎代码文件:rename()函数.py

◎数据文件:供应商信息表.xlsx

如右图所示,工作簿“供应商信息表.xlsx”位于文件夹“F:\python\第1章\工作信息表”中,现要将该工作簿重命名为“供应商.xlsx”,并移至文件夹“F:\python”。这里用rename()函数进行演示,代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\工作信息表\\供应商信息表.xlsx') # 指定要重命名并移动的工作簿
3 p.rename('F:\\python\\供应商.xlsx') # 执行工作簿的重命名和移动操作

运行以上代码后,文件夹“F:\python\第1章\工作信息表”中的工作簿“供应商信息表.xlsx”就被移动到文件夹“F:\python”中,且被重命名为“供应商.xlsx”,如右图所示。

1.2.6 iterdir()函数——罗列文件夹的内容

路径对象的iterdir()函数用于罗列指定文件夹中所有文件和子文件夹的路径。其语法格式如下:

表达式.iterdir()

参数说明:

表达式:一个路径对象,指向一个文件夹。

iterdir()函数通常配合for语句使用,将获取的路径逐个取出,以便做进一步处理。

应用场景1 罗列指定文件夹的内容

◎代码文件:iterdir()函数1.py

◎数据文件:工作信息表1(文件夹)

假设计算机硬盘中有一个文件夹“F:\python\第1章\工作信息表1”,其内容如右图所示。现要获取该文件夹中所有文件和子文件夹的路径,可以结合使用iterdir()函数和for语句来实现,演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\工作信息表1') # 指定一个文件夹的路径
3 p1 = p.iterdir() # 获取指定文件夹中所有文件和子文件夹的路径
4 for i in p1: # 遍历获取结果
5       print(i) # 输出获取的路径

代码运行结果如下:


1 F:\python\第1章\工作信息表1\上半年销售统计
2 F:\python\第1章\工作信息表1\供应商信息表.xlsx
3 F:\python\第1章\工作信息表1\出库表.xlsx
4 F:\python\第1章\工作信息表1\员工档案表.xlsx
5 F:\python\第1章\工作信息表1\库存表.xlsx
6 F:\python\第1章\工作信息表1\采购合同.pdf

从运行结果可以看出,因为第2行代码给出的文件夹路径是绝对路径,所以iterdir()函数返回的路径也是绝对路径。如果第2行代码给出的是相对路径,则返回的路径会是相对路径。此外,iterdir()函数的罗列结果是乱序排列的,并且只进行一级罗列,即在罗列出子文件夹后,并不会继续往下罗列子文件夹的内容。

应用场景2 判断指定文件夹是否为空文件夹

◎代码文件:iterdir()函数2.py

◎数据文件:上半年销售统计(文件夹)

假设计算机硬盘中有一个文件夹“F:\python\第1章\工作信息表1\上半年销售统计”,现要判断该文件夹是否为空文件夹(即其中是否还有其他文件或子文件夹),可以使用iterdir()函数来实现,演示代码如下:


1 from pathlib import Path  # 导入pathlib模块中的Path对象
2  p = Path('F:\\python\\第1章\\工作信息表1\\上半年销售统计')  # 指定一个文件夹的路径
3 p1 = p.iterdir()  # 获取指定文件夹中所有文件和子文件夹的路径
4 if len(list(p1)) == 0:  # 将获取结果转换为列表并判断列表的长度是否为0
5     print(p, '是空文件夹')  # 如果列表长度为0,则是空文件夹
6 else:
7     print(p, '不是空文件夹')  # 如果列表长度不为0,则不是空文件夹

上述代码的编写思路是先用iterdir()函数罗列指定文件夹中所有文件和子文件夹的路径,再判断获取的路径的个数,如果为0则是空文件夹,反之则不是空文件夹。第4行代码先用list()函数将iterdir()函数的获取结果转换为列表,再用len()函数获取列表长度,即可得到路径个数。

代码运行结果如下,可以看出指定文件夹不是空文件夹。


1 F:\python\第1章\工作信息表1\上半年销售统计 不是空文件夹

1.2.7 glob()函数和rglob()函数——罗列并筛选文件夹的内容

路径对象的glob()函数和rglob()函数不仅能像iterdir()函数那样罗列文件夹的内容,而且能对罗列结果进行筛选,只返回名称符合特定条件的文件和子文件夹的路径。其语法格式如下:

表达式.glob/rglob(pattern)

参数说明:

表达式:一个路径对象,指向一个文件夹。

pattern:一个字符串,代表筛选条件。在筛选条件中可使用通配符“*”和“?”来进行模糊匹配,其中“*”代表匹配任意数量(包括0个)的任意字符,“?”代表匹配单个任意字符。例如:'*'表示匹配所有文件夹或文件;'*统计*'表示匹配名称包含“统计”的文件夹或文件;'*.txt'表示匹配扩展名为“.txt”的文件;'统计*.p?'表示匹配文件名以“统计”开头,扩展名为两个字符并以字母p开头的文件。如果在筛选条件中不使用通配符,则进行精确匹配。例如,'统计表.csv'表示精确匹配文件名为“统计表.csv”的文件。

glob()函数和rglob()函数的区别是:glob()函数一般和iterdir()函数一样只进行一级罗列,如果在筛选条件前加上“**/”,如“**/*.txt”,则会进行递归罗列,即在罗列出子文件夹后,继续往下罗列子文件夹的内容,如果子文件夹下还有子文件夹,则接着往下罗列,直到不能罗列为止;rglob()函数则会始终进行递归罗列。

具体到实际应用,这两个函数可以用于按关键词搜索文件夹或文件,批量获取特定类型文件的路径,等等。

应用场景1 罗列指定文件夹中的所有工作簿

◎代码文件:glob()函数.py

◎数据文件:工作信息表2(文件夹)

右图所示为文件夹“F:\python\第1章\工作信息表2”中的子文件夹和文件,下面使用glob()函数对该文件夹的内容进行一级罗列,并筛选出所有扩展名为“.xlsx”的工作簿,返回它们的路径。演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\工作信息表2') # 指定一个文件夹的路径
3 workbook = p.glob('*.xlsx') # 获取指定文件夹中所有工作簿的路径
4 for i in workbook: # 遍历获取结果
5     print(i) # 逐个输出工作簿的路径

代码运行结果如下:


1 F:\python\第1章\工作信息表2\供应商信息表.xlsx
2 F:\python\第1章\工作信息表2\出库表.xlsx
3 F:\python\第1章\工作信息表2\员工档案表.xlsx
4 F:\python\第1章\工作信息表2\库存表.xlsx

从运行结果可以看出,因为第2行代码给出的文件夹路径是绝对路径,所以glob()函数返回的路径也是绝对路径。如果第2行代码给出的是相对路径,则返回的路径会是相对路径。

应用场景2 罗列文件夹及其子文件夹中的所有工作簿

◎代码文件:rglob()函数1.py

◎数据文件:工作信息表2(文件夹)

假设在文件夹“F:\python\第1章\工作信息表2”的子文件夹“上半年销售统计”下还有一些文件,如右图所示。现在要获取文件夹“F:\python\第1章\工作信息表2”和子文件夹“上半年销售统计”中扩展名为“.xlsx”的所有工作簿的路径,可以使用rglob()函数进行递归罗列。演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\工作信息表2') # 指定一个文件夹的路径
3 workbook = p.rglob('*.xlsx') # 获取指定文件夹及其子文件夹中所有工作簿的路径
4 for i in workbook: # 遍历获取结果
5     print(i) # 逐个输出工作簿的路径

第3行代码使用rglob()函数进行递归罗列,如果要使用glob()函数进行递归罗列,则筛选条件要修改为'**/*.xlsx'。

代码运行结果如下:


1 F:\python\第1章\工作信息表2\供应商信息表.xlsx
2 F:\python\第1章\工作信息表2\出库表.xlsx
3 F:\python\第1章\工作信息表2\员工档案表.xlsx
4 F:\python\第1章\工作信息表2\库存表.xlsx
5 F:\python\第1章\工作信息表2\上半年销售统计\1月销售表.xlsx
6 F:\python\第1章\工作信息表2\上半年销售统计\2月销售表.xlsx
7 F:\python\第1章\工作信息表2\上半年销售统计\3月销售表.xlsx
8 F:\python\第1章\工作信息表2\上半年销售统计\4月销售表.xlsx
9 F:\python\第1章\工作信息表2\上半年销售统计\5月销售表.xlsx
10 F:\python\第1章\工作信息表2\上半年销售统计\6月销售表.xlsx

从运行结果可以看出,因为第2行代码给出的文件夹路径是绝对路径,所以rglob()函数返回的路径也是绝对路径。如果第2行代码给出的是相对路径,则返回的路径会是相对路径。

应用场景3 罗列工作簿时剔除临时文件

◎代码文件:rglob()函数2.py

◎数据文件:采购表(文件夹)

用Excel处理工作簿时,如果Excel程序意外崩溃,工作簿没有正常关闭,在文件夹中就会留下文件名以“~$”开头的临时文件(默认为隐藏文件,需要经过一定的设置才能显示出来)。右图所示为文件夹“F:\python\第1章\采购表”的内容,其中有一些临时文件。如果想在罗列文件夹内容时剔除这些临时文件,可以结合使用1.1.5节介绍的name属性来实现。演示代码如下:


1 from pathlib import Path  # 导入pathlib模块中的Path对象
2 p = Path('F:\\python\\第1章\\采购表')  # 指定一个文件夹的路径
3 workbook = p.rglob('*.xlsx')  # 获取文件夹中所有工作簿的路径
4 for i in workbook:  # 遍历获取结果
5     if i.name.startswith('~$'):  # 如果获取的路径中文件名以“~$”开头
6         continue  # 提前结束本轮循环
7     print(i)  # 输出获取的路径

第5行代码先用路径对象的name属性提取文件名,得到的是一个字符串,再用字符串的startswith()函数判断文件名是否以“~$”开头。如果判断结果为True,则执行第6行代码中的continue语句,跳过循环中剩余的代码,回到第4行代码,开始下一轮循环;如果判断结果为False,则继续执行第7行代码,输出获取的路径。

代码运行结果如下:


1 F:\python\第1章\采购表\1月.xlsx
2 F:\python\第1章\采购表\2月.xlsx
3 F:\python\第1章\采购表\3月.xlsx

1.2.8 stat()函数——获取文件夹或文件的状态信息

路径对象的stat()函数用于获取指定文件夹或文件的各种状态信息,如大小、创建时间、修改时间、用户权限等。其语法格式如下:

表达式.stat()

参数说明:

表达式:一个路径对象。

stat()函数的返回值是一个包含各种状态信息的os.stat_result对象,还需要通过访问该对象的不同属性来提取特定的状态信息。os.stat_result对象的属性会根据操作系统的不同而变化,这里只介绍Windows操作系统下常用的一些属性的返回值,如下表所示。

上表中与时间相关的3个属性的返回值是时间戳格式,表示从格林尼治时间(GMT)1970年1月1日0时0分0秒至某个时间点的总秒数,如1604996297。这种格式不符合我们的日常阅读习惯,需要使用一些日期和时间处理函数进行格式化,后面会结合具体案例进行讲解。

应用场景1 将指定文件夹下的文件按大小排序

◎代码文件:stat()函数1.py

◎数据文件:工作信息表(文件夹)

文件夹“F:\python\第1章\工作信息表”的内容如右图所示,本案例要罗列该文件夹中的文件,并按照文件大小做降序排序。演示代码如下:


1 from pathlib import Path  # 导入pathlib模块中的Path对象
2  def file_size(file_path):  # 定义一个函数,用于根据路径获取文件大小,作为排序的依据
3     return file_path.stat().st_size  # 将函数的返回值设置为文件大小
4 p = Path('F:\\python\\第1章\\工作信息表')  # 指定一个文件夹的路径
5 p_list = list(p.iterdir())  # 罗列指定文件夹的内容,并转换为列表
6  p_list.sort(key=file_size, reverse=True)  # 对列表元素进行排序,排序依据是文件大小,排序方式是降序排序
7 for i in p_list:  # 遍历排序后的列表
8     print(i.name, file_size(i), 'bytes')  # 输出文件名和文件大小

代码运行结果如下:


1 采购合同.pdf 108110 bytes
2 出库表.xlsx 14629 bytes
3 库存表.xlsx 14623 bytes
4 员工档案表.xlsx 14348 bytes
5 供应商信息表.xlsx 13695 bytes

第5行代码先用路径对象的iterdir()函数罗列指定文件夹的内容,接着用list()函数将罗列结果转换为列表,以便进行排序。

第6行代码使用列表的sort()函数对列表元素进行排序,该函数的语法格式如下:

表达式.sort(key,reverse)

参数说明:

表达式:一个列表。

key:用于指定一个单参数的函数,sort()函数会将每个列表元素传入该函数,并使用返回值作为排序时比较大小的依据。如果省略该参数,则直接对列表元素进行比较大小和排序。

reverse:用于指定排序方式。设置为False或省略该参数表示升序排序,设置为True表示降序排序。

在第6行代码中,为key参数指定的单参数函数是在第2行和第3行代码中定义的file_size()函数。file_size()函数的参数是一个路径对象,函数内部的第3行代码先调用路径对象的stat()函数获取文件的状态信息,再调用st_size属性从状态信息中提取文件的大小,作为函数的返回值。因此,在第6行代码的执行过程中,sort()函数会将列表p_list中的路径对象分别传入file_size()函数,然后根据file_size()函数返回的文件大小对列表p_list中的路径对象进行排序,排序的方式是降序排序(reverse=True)。

应用场景2 获取指定文件的最近修改时间并进行格式化

◎代码文件:stat()函数2.py

◎数据文件:供应商信息表.xlsx

本案例要获取文件夹“F:\python\第1章\工作信息表”中工作簿“供应商信息表.xlsx”的最近修改时间,并按照日常阅读习惯进行格式化。演示代码如下:


1 from pathlib import Path # 导入pathlib模块中的Path对象
2 from datetime import datetime # 导入datetime模块中的datetime对象
3 p = Path('F:\\python\\第1章\\工作信息表\\供应商信息表.xlsx') # 指定一个文件路径
4 file_time = p.stat().st_mtime # 获取文件的状态信息并提取最近修改时间
5 file_time = datetime.fromtimestamp(file_time) # 将提取的时间转换为当前操作系统时区的时间
6 file_time_new = file_time.strftime('%Y年%m月%d日 %H:%M:%S') # 对转换后的时间进行格式化
7 print(file_time_new) # 输出格式化后的时间

代码运行结果如下:


1 2021年07月27日 14:14:13

第2行代码导入datetime模块中的datetime对象。datetime模块是Python的内置模块,专用于处理日期和时间数据。

第4行代码先调用路径对象的stat()函数获取文件的状态信息,再调用st_mtime属性从状态信息中提取文件的最近修改时间。根据前面的讲解,提取到的是一个时间戳,因此在第5行代码调用datetime对象的fromtimestamp()函数将时间戳转换为当前操作系统时区的时间,然后在第6行代码调用strftime()函数按照自定义的格式字符串对转换后的时间进行格式化。格式字符串中的“%Y”“%m”“%d”等是格式代码,更多格式代码可以参考datetime模块的官方文档https://docs.python.org/3.8/library/datetime.xhtml#strftime-and-strptime-format-codes。 oin+p95lrhlzeS6sSiUYIYDEuACDgjTghjpgFp7NeFh7WKGwC+fRYt0P2PMou4kW

点击中间区域
呼出菜单
上一章
目录
下一章
×