掌握了pathlib模块的路径操作,就可以通过构造好的路径对象对文件夹或文件执行实际操作了,如文件夹或文件的新建、删除、重命名、状态信息获取等。本节就来讲解相关的知识。
路径对象的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”的工作簿。
路径对象的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
路径对象的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章”下的空文件夹“信息表”就被删除了。
路径对象的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() # 根据路径删除工作簿
路径对象的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”,如右图所示。
路径对象的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\上半年销售统计 不是空文件夹
路径对象的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
路径对象的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。