Python pathlib 包详解:现代文件路径处理方式
pathlib 是 Python 3.4 引入的内置库,提供了面向对象的文件系统路径处理方式,相比传统的 os.path 模块,它更直观、更易读,也更符合 Python 的风格。
一、pathlib 核心功能与优势
- 面向对象的 API,操作路径更直观
- 路径拼接、分割等操作更简洁
- 内置文件读写、属性查询等方法
- 跨平台兼容,自动处理不同系统的路径分隔符
- 支持链式调用,代码更优雅
二、基本使用与路径创建
创建路径对象
from pathlib import Path
# 当前工作目录
cwd = Path.cwd()
print("当前工作目录:", cwd)
# 用户主目录
home = Path.home()
print("用户主目录:", home)
# 手动创建路径
path = Path("/usr/local/bin")
relative_path = Path("docs", "guide.md") # 相对路径
combined_path = Path.home() / "projects" / "python" # 使用 / 运算符拼接
print("组合路径:", combined_path)
三、路径属性与信息获取
p = Path("/Users/username/projects/flask/app.py")
# 基本属性
print("文件名:", p.name) # 带扩展名的文件名:app.py
print("纯文件名:", p.stem) # 不带扩展名的文件名:app
print("扩展名:", p.suffix) # 扩展名:.py
print("父目录:", p.parent) # 父目录路径:/Users/username/projects/flask
print("根目录:", p.root) # 根目录:/
print("是否绝对路径:", p.is_absolute()) # True
# 多重扩展名处理
archive = Path("data.tar.gz")
print("所有扩展名:", archive.suffixes) # ['.tar', '.gz']
print("完整扩展名:", ''.join(archive.suffixes)) # .tar.gz
四、路径操作与修改
p = Path("/Users/username/docs/report.txt")
# 修改文件名/扩展名
new_name = p.with_name("summary.txt")
print("新文件名:", new_name) # /Users/username/docs/summary.txt
new_suffix = p.with_suffix(".md")
print("新扩展名:", new_suffix) # /Users/username/docs/report.md
# 路径拼接
subpath = p.parent / "images" / "chart.png"
print("子路径:", subpath) # /Users/username/docs/images/chart.png
# 相对路径计算
other_path = Path("/Users/username/projects/app.py")
relative = p.relative_to(Path.home())
print("相对路径:", relative) # docs/report.txt
五、文件系统交互
file_path = Path("example.txt")
# 文件读写
file_path.write_text("Hello, pathlib!") # 写入文本
content = file_path.read_text() # 读取文本
print("文件内容:", content)
# 二进制读写
bin_path = Path("data.bin")
bin_path.write_bytes(b"Binary data")
bin_content = bin_path.read_bytes()
print("二进制内容:", bin_content)
# 文件属性
print("文件大小:", file_path.stat().st_size) # 字节数
print("创建时间:", file_path.stat().st_ctime) # 创建时间戳
print("修改时间:", file_path.stat().st_mtime) # 修改时间戳
六、目录操作与文件查找
# 创建目录(递归创建)
new_dir = Path("docs/tutorial/examples")
new_dir.mkdir(parents=True, exist_ok=True) # parents=True 允许递归创建
# 列出目录内容
for item in Path.cwd().iterdir():
if item.is_dir():
print(f"目录: {item.name}")
elif item.is_file():
print(f"文件: {item.name}")
# 查找文件(glob 模式)
# 查找当前目录下所有 .py 文件
py_files = list(Path.cwd().glob("*.py"))
print("Python 文件:", py_files)
# 递归查找所有 .txt 文件
txt_files = list(Path.cwd().rglob("*.txt")) # rglob 递归查找
print("所有文本文件:", txt_files)
# 检查路径是否存在
print("是否存在:", new_dir.exists())
print("是否是文件:", file_path.is_file())
print("是否是目录:", new_dir.is_dir())
七、文件移动与删除
source = Path("old_file.txt")
dest = Path("new_dir/new_file.txt")
# 创建测试文件
source.write_text("Test content")
# 移动文件
source.rename(dest) # 可以移动并改名
# 复制文件(pathlib 本身不直接支持,需结合 shutil)
import shutil
shutil.copy2(dest, Path("backup.txt")) # 保留元数据的复制
# 删除文件
Path("backup.txt").unlink() # 删除文件
# 删除目录(空目录)
empty_dir = Path("empty_dir")
empty_dir.mkdir(exist_ok=True)
empty_dir.rmdir() # 只能删除空目录
# 删除非空目录(需使用 shutil)
import shutil
shutil.rmtree(new_dir.parent) # 递归删除目录及其内容
八、与 os.path 的对比
| 功能 | os.path 方式 | pathlib 方式 |
|---|---|---|
| 获取文件名 | os.path.basename(path) | Path(path).name |
| 获取目录名 | os.path.dirname(path) | Path(path).parent |
| 路径拼接 | os.path.join(a, b) | Path(a) / b |
| 检查是否为文件 | os.path.isfile(path) | Path(path).is_file() |
| 获取扩展名 | os.path.splitext(path)[1] | Path(path).suffix |
九、实际应用场景示例
def process_markdown_files(root_dir):
"""查找并处理所有 markdown 文件"""
root = Path(root_dir)
# 检查目录是否存在
if not root.exists() or not root.is_dir():
print(f"目录不存在: {root}")
return
# 递归查找所有 .md 文件
md_files = root.rglob("*.md")
for file in md_files:
try:
# 读取文件内容
content = file.read_text(encoding="utf-8")
# 简单处理:统计字符数
char_count = len(content)
word_count = len(content.split())
print(f"文件: {file.relative_to(root)}")
print(f" 字符数: {char_count}")
print(f" 单词数: {word_count}\n")
except Exception as e:
print(f"处理 {file} 时出错: {e}")
# 使用函数
process_markdown_files("docs")
总结
pathlib 提供了一种更现代、更面向对象的文件路径处理方式,它将路径视为对象而非字符串,使得代码更易读、更易维护。对于新的 Python 项目,推荐使用 pathlib 替代传统的 os.path 模块。
通过 pathlib,你可以用更少的代码完成更多的文件操作,同时避免了许多与路径处理相关的常见错误,特别是在跨平台开发时。
1709

被折叠的 条评论
为什么被折叠?



