目录
1. pathlib
是什么?
在日常的 Python 编程中,文件和目录的路径处理是一个常见且重要的任务。许多开发者习惯使用 os
模块来完成这些操作,例如获取文件列表、检查文件是否存在等。然而,直接将路径作为字符串进行处理可能会导致代码冗长、复杂,且容易出错。
自 Python 3.4 起,官方引入了 pathlib
模块,提供了一种更加优雅和高效的方式来处理文件系统路径。pathlib
通过将路径表示为对象,支持面向对象的路径操作,使代码更加简洁、可读。
本文将深入探讨 pathlib
模块的强大功能,通过实例对比展示其相对于 os
模块的优势,帮助你在文件和目录操作中事半功倍。
1.1 os
的局限性
假设我们需要获取某个目录下的所有 .txt
文件,使用 os
模块时,可能需要编写如下代码:
import os
directory = "/Users/yourname/Documents"
txt_files = [
os.path.join(directory, f)
for f in os.listdir(directory)
if os.path.isfile(os.path.join(directory, f)) and f.endswith(".txt")
]
这段代码中,我们需要多次调用 os.path
的方法来拼接路径和检查文件类型,代码显得繁琐且不直观。
1.2 pathlib
的优势
使用 pathlib
,上述操作可以简化为:
from pathlib import Path
directory = Path("/Users/yourname/Documents")
txt_files = list(directory.glob("*.txt"))
pathlib
将文件系统路径视为对象,提供了丰富的方法来操作路径,使代码更加简洁清晰。许多大型开源项目都在使用 pathlib
,足以证明其强大之处。
2. 路径操作详解
pathlib
模块的核心是 Path
类,它为文件和目录的操作提供了面向对象的接口。
2.1 路径对象创建
获取当前目录:
from pathlib import Path
current_dir = Path.cwd()
print(current_dir)
# 输出示例:/Users/yourname/Projects
获取用户主目录:
home_dir = Path.home()
print(home_dir)
# 输出示例:/Users/yourname
通过字符串定义路径:
p = Path("my_folder")
print(p)
# 输出:my_folder
用 /
运算符连接路径:
data_folder = Path(".") / "data"
csv_file = data_folder / "dataset.csv"
print(data_folder)
# 输出:data
print(csv_file)
# 输出:data/dataset.csv
使用 /
运算符可以直观地拼接路径,而不需要调用 os.path.join
。
2.2 路径属性检查
判断路径是否存在:
data_folder.exists()
# 返回 True 或 False
判断是否为目录或文件:
data_folder.is_dir()
# 返回 True 或 False
csv_file.is_file()
# 返回 True 或 False
获取绝对路径:
absolute_path = csv_file.resolve()
print(absolute_path)
# 输出示例:/Users/yourname/Projects/data/dataset.csv
转换路径为字符串:
path_str = str(Path.home())
print(path_str)
# 输出:/Users/yourname
值得注意的是,现代的许多库(如 pandas
、matplotlib
、seaborn
等)都支持 Path
对象作为参数,进一步提升了 pathlib
的实用性。
3. Path 对象的属性和方法
Path
对象拥有许多有用的属性和方法,方便我们获取路径的各种信息。
3.1 获取路径的组成部分
访问父级目录:
image_file = Path("images/sample.png").resolve()
print(image_file.parent)
# 输出示例:/Users/yourname/Projects/images
获取文件名称:
print(image_file.name)
# 输出:sample.png
获取文件的前缀和后缀:
print(image_file.stem)
# 输出:sample
print(image_file.suffix)
# 输出:.png
分解路径为各个部分:
print(image_file.parts)
# 输出:('/', 'Users', 'yourname', 'Projects', 'images', 'sample.png')
列出所有父级目录:
for parent in image_file.parents:
print(parent)
输出:
/Users/yourname/Projects/images
/Users/yourname/Projects
/Users/yourname
/Users
/
3.2 修改路径信息
更改文件名或扩展名:
new_image_file = image_file.with_name("updated_sample.jpg")
print(new_image_file)
# 输出示例:/Users/yourname/Projects/images/updated_sample.jpg
修改文件后缀:
jpg_file = image_file.with_suffix(".jpg")
print(jpg_file)
# 输出示例:/Users/yourname/Projects/images/sample.jpg
4. 文件操作
pathlib
不仅可以处理路径,还提供了方便的方法来操作文件。
4.1 文件的读写
写入文本或二进制数据:
markdown_file = data_folder / "notes.md"
# 写入文本内容(会覆盖原有内容)
markdown_file.write_text("# 这是一个示例 Markdown 文件")
# 写入二进制内容
binary_file = data_folder / "data.bin"
binary_file.write_bytes(b'\x10\x20\x30\x40')
读取文本或二进制数据:
content = markdown_file.read_text()
print(content)
# 输出:# 这是一个示例 Markdown 文件
binary_content = binary_file.read_bytes()
print(binary_content)
# 输出:b'\x10\x20\x30\x40'
向文件追加内容:
with markdown_file.open(mode="a") as file:
file.write("\n## 追加的新章节")
print(markdown_file.read_text())
# 输出:
# # 这是一个示例 Markdown 文件
# ## 追加的新章节
4.2 文件的重命名与删除
重命名文件:
renamed_file = markdown_file.with_stem("renamed_notes")
markdown_file.rename(renamed_file)
# 文件已重命名为 data/renamed_notes.md
获取文件大小:
file_size = renamed_file.stat().st_size
print(file_size)
# 输出文件大小(字节数)
获取文件的修改时间:
from datetime import datetime
mod_time = datetime.fromtimestamp(renamed_file.stat().st_mtime)
print(mod_time)
# 输出示例:2023-08-15 14:20:30.123456
删除文件:
renamed_file.unlink(missing_ok=True)
# 文件已被删除
missing_ok=True
表示如果文件不存在,不会引发异常。
5. 目录处理
pathlib
同样提供了丰富的方法来创建、遍历和删除目录。
5.1 创建与移除目录
新建目录:
new_directory = Path("data/new_folder")
new_directory.mkdir(parents=True, exist_ok=True)
parents=True
:如果父目录不存在,自动创建。exist_ok=True
:如果目录已存在,不会引发异常。
删除目录:
new_directory.rmdir()
# 注意:只能删除空目录
5.2 遍历目录内容
列举目录中的内容:
for item in Path.home().iterdir():
print(item)
输出示例:
/Users/yourname/Documents
/Users/yourname/Downloads
/Users/yourname/Pictures
...
使用 glob
查找匹配模式的文件:
# 查找主目录下的所有 .txt 文件
home = Path.home()
text_files = list(home.glob("*.txt"))
print(len(text_files))
# 输出:找到的 .txt 文件数量
使用 rglob
进行递归搜索:
# 递归查找所有子目录中的 .txt 文件
all_text_files = list(home.rglob("*.txt"))
print(len(all_text_files))
# 输出:递归找到的 .txt 文件数量
6. Path
类的核心功能概览
本节对之前的内容进行了总结,方便大家速查。
实例化路径对象:
from pathlib import Path
# 当前目录
current_path = Path()
# 指定路径
specific_path = Path('/usr/local/bin')
路径操作方法:
- 拼接路径:
path / 'subdir' / 'file.txt'
- 获取绝对路径:
path.resolve()
- 检查路径是否存在:
path.exists()
- 判断是否为目录或文件:
path.is_dir()
、path.is_file()
- 创建目录:
path.mkdir(parents=True, exist_ok=True)
访问路径信息:
- 获取文件名:
path.name
- 获取文件前缀:
path.stem
- 获取文件后缀:
path.suffix
- 获取父目录:
path.parent
文件读写操作:
- 读取文本内容:
path.read_text()
- 写入文本内容:
path.write_text("内容")
- 读取二进制内容:
path.read_bytes()
- 写入二进制内容:
path.write_bytes(b'数据')
遍历目录内容:
- 遍历当前目录下的文件:
path.glob('*')
- 递归遍历所有子目录:
path.rglob('*')
Ref
[1] https://www.bilibili.com/read/cv25592439/
[2] https://github.com/chris1610/pbpython/blob/master/extras/Pathlib-Cheatsheet.pdf
[3] https://docs.python.org/zh-cn/3/library/pathlib.html