一、pathlib 模块简介
pathlib 是Python 3.4版本开始加入的 路径处理模块。它将路径本身变成一个对象,这个对象自带各种操作方法,代码写起来更直观、优雅。但 pathlib 不会取代 os.path。
os.path 的路径 是字符串(‘C:/Users/test.txt')
pthlib 的路径是对象(Path(’C:/Users/test.txt')
根据官方文档,pathlib 模块共分为 6个部分:
PurePath:
纯路径。
拼接路径、取文件名、取后缀、判断路径是否以指定的后缀结尾等。
不读取硬盘(不能创建、删除文件),且不区分操作系统,因此运行速度快
PurePosixPath、PureWindowsPath:
用于处理不同操作系统的斜杠
PurePosixPath:专门处理 / 斜杠的路径,Linux系统的 /home/user
PureWindowsPath:专门处理 \ 反斜杠的路径,Windows系统的 C:\Users
Path:
实体路径
继承 PurePath 的所有能力,并增加访问磁盘的功能,因此可创建、删除文件夹,读取文件内容等。
PosixPath、WindowsPath:
是 Path 在不同操作系统下的具体实现
在 Windows 系统中导入 Path,那么 Path 即为 WindowsPath,同样的在Linux系统中导入 Path 即为 PosixPath
我们要学习的便是 Path
二、Path 的常用方法
1、系统方法
(1)Path.cwd()
获取当前所在目录
它自动识别了操作系统的类型,并在返回值中体现出来。和 os 模块的用法基本差不多
(2)Path.home()
获取用户主目录
os 模块获取用户主目录可通过 os.environ 获取到环境变量,然后根据操作系统的类型通过 os.environ['USERPROFILE'] (Windows系统)、os.environ['HOME'] (Linux系统)来获取。
(3)Path.chdir()
Path.chdir() 是 Ppython 3.11版本以后的新特性
使用方法((由于我的系统环境问题,无法复现):
p = Path(r"E:\os_path_2")
p.chdir()
(4)Path.expanduser()
将路径字符串中的 ~ 替换成当前用户的主目录路径,作用和 os.path.expanduser('~')完全一样,区别在于 Path.expanduser()返回的是一个 Path 对象。
(5)Path.resolve()
将路径解析为绝对路径
示例1:将相对路径替换成绝对路径
在 E:\os_path_2 目录下有一个 test.txt的文件,先切换到目录下(由于环境问题,我使用的是 os.chdir()
示例2:将路径中的 .. 和 . 消除
.. :返回上一级;. :当前目录
原始路径为:"E:\os_path_2\test\next_file\test2\test_2.txt"
得到的结果并不是原始路径,而且还不相同,那么说明一个情况:Path.resolve() 只负责处理,不负责判断是否存在。如果需要判断文件路径是否存在则需要使用到 .exists() 来进行判断。
再来说一个 .resolve()的参数
Path.resolve() 默认参数为 strict=False,可指定为 strict=True
什么作用?再来试一下:
路径不存在时会报错,相当于使用 .exists(),只不过一个返回的是 False,一个直接抛出 FileNotFoundError 错误。
(6)Path.absolute()
负责补全路径头,不负责清理路径中的 .. 或 .
通过上面这个示例可以看出 Path.resolve() 和 Path.asbolute() 的不同:
.absolute():是将当前所在目录的路径补全在了 p4 的前面,没有处理路径中的 ..
.resolve():将当前所在目录的路径补在了 p4 的前面,而且处理了路径中的 ..
2、查询与判断
Path.exists() :判断路径是否存在
Path.is_dir():判断是否为目录
Path.is_file():判断是否为普通文件
Path.is_symlink():判断是否为符号连接
Path.is_absolute():判断是否为绝对路径
Path.stat():获取文件状态信息
Path.lstat():获取文件状态信息(不跟踪符号链接)
Path.owner():获取文件所有者(Unix)
Path.group():获取文件所属组(Unix)
Path.readlink():读取符号链接的目标路径
3、遍历与搜索
Path.iterdir()
遍历指定目录下的所有内容,得到的是一个可迭代的对象
如果目录中有子目录不会再遍历子目录
Path.glob() :
通配符搜索当前目录,可查找特定的文件
Path.rglob():
递归通配符搜索所有子目录
查找指定目录下包括子目录中所有指定类型的文件
Path.walk():
递归遍历目录树
Path.walk() 是 Python 3.12以后引入的一个新方法,它和 os.walk() 的用法基本一致,但返回的是生成器。可通过 for root, dirs, files 来循环。
root:当前目录的完整绝对路径
dirs:当前目录下所有子目录
files:当前目录下所有文件
通过示例可以看到 Path.walk() 是逐层遍历的过程
4、创建与删除
Path.mkdir(mode=0o777, parents=True, exist_ok=True):
创建目录
mode=0o777 :
用于设置目录的权限(不常用)
parents=False/True:
是否自动创建路径中所有不存在的父目录
当parents=True时相当于os.makedirs()
exist_ok=False/True:
如果目标目录已存在,是否报错
Path.touch(mode=0o777, exist_ok=True):
创建文件或更新时间戳
Path.rmdir():
删除空目录
Path.unlink(missing_ok=False):
删除文件
5、文件操作
Path.open(mode='r'):打开文件,和os模块的一样
Path.read_text(encoding=None):读取文本文件
Path.write_text(data, encoding=None):写入文本文件,覆盖写入
Path.read_test() 和 Path.write_text() 只适合操作小文件,如果需要操作大文件则需要使用 Path.open()。
在使用时务必加上 encoding 参数,以免报错。
6、重命名与移动
Path.rename(target):重命名文件或目录
Path.replace(target):重命名并覆盖已存在的目录
以上就是 Path 的常用方法,我将它们分成了6类,基本可以满足日常需求。
四、一个示例
os模块学习过程中,做了一个桌面文件整理的脚本,在学习 pathlib 后,对其进行了修改。
根据文件扩展名对桌面文件进行归类整理。
# import os from pathlib import Path import shutil import datetime # 1、定义变量 # 获取当前用户主目录 home = Path.home() # 定义source_path 变量,赋值为桌面路径 source_path = home / "Desktop" # 定义目标主目录 desc_path = home / "Desktop" / "files" # 通过字典定义不同的文件类型归类到指定的分类目录,"suffix_***" 名称可以自定义,文件分类也可自定义 suffix_dict = { "suffix_txt": [".txt"], "suffix_zip" : [".tar.gz", ".zip", ".rar", ".7z", ".tar", ".gz", ".bz2", ".xz"], "suffix_doc" : [".doc", ".docx"], "suffix_pdf" : [".pdf"], "suffix_excel" : [".xls", ".xlsx"], "suffix_powerpoint" : [".ppt", ".pptx"], "suffix_image" : [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", ".webp"], "suffix_video" : [".mp4", ".avi", ".mkv", ".wmv", ".mov", ".flv", ".webm"], "suffix_audio" : [".mp3", ".wav", ".aac", ".ogg", ".flac"], "suffix_exe" : [".exe", ".msi"] } def makedirs_file(): # 创建主目录 # .mkdir(parents=True, exist_ok=True)中, parents=True 表示创建父目录, exist_ok=True 表示如果目录已存在则不创建,不会报错 desc_path.mkdir(parents=True, exist_ok=True) # 创建子目录 for key in suffix_dict.keys(): (desc_path / key).mkdir(parents=True, exist_ok=True) def get_and_move_file(source_path): # 创建目录 makedirs_file() # 遍历桌面 for file_path in source_path.iterdir(): # 如果脚本在 Desktop 下,则跳过,即不移动脚本文件 if file_path.name == Path(__file__).name: continue # 只处理文件,不处理文件夹 if not file_path.is_file(): continue # 获取文件名和扩展名 name_without_ext = file_path.stem ext = file_path.suffix # 查找属于哪个分类 target_key = None for key, suffix_list in suffix_dict.items(): if ext in suffix_list: target_key = key break # 如果找不到匹配,则跳过 if target_key is None: print(f"{file_path.name} 无法识别的文件类型") continue # 定义目标路径 target_folder = desc_path / target_key target_path = target_folder / file_path.name # 重名处理,如果存在重名的文件,则以当前系统时间重命名文件 if target_path.exists(): timestamp = datetime.datetime.now().strftime("%Y%m%d%H%M%S") new_name = f"{name_without_ext}_{timestamp}{ext}" target_path = target_folder / new_name print(f"⚠️ {file_path.name} 已存在,重命名为 {new_name}") # 移动文件 try: shutil.move(file_path, target_path) print(f"✅ 移动 {file_path.name} → {target_folder}") except Exception as e: print(f"❌ 移动失败:{file_path.name},错误:{e}") if __name__ == "__main__": get_and_move_file(source_path)学习中,如有不足还请指正!