我们必须知道,我们终将知道。
📂 路径处理
pathlib 是 Python 处理文件路径的现代工具,提供面向对象、跨平台的路径处理 API。
📌 本节要点
- pathlib 优先:新项目推荐
Path对象,代码更短、跨平台、面向对象 /运算符:路径拼接,比os.path.join更直观- 属性访问:
.name/.stem/.suffix/.parent替代os.path.basename等函数 - 小文件读写:
read_text()/write_text()一行搞定 :::
os.path vs pathlib
传统的 os.path 把路径当作字符串,所有操作都是函数调用:
import os
# 传统写法:字符串拼接,平台相关
base = '/home/user'
full = os.path.join(base, 'docs', 'readme.txt')
name = os.path.basename(full)
parent = os.path.dirname(full)
exists = os.path.exists(full)
而 pathlib 把路径封装成 Path 对象,操作更直观、更链式:
from pathlib import Path
# 现代写法:面向对象,跨平台
base = Path('/home/user')
full = base / 'docs' / 'readme.txt'
name = full.name
parent = full.parent
exists = full.exists()
对于新项目,强烈推荐使用 pathlib:代码更短、可读性更好、自动处理平台差异(Windows 用 \,Linux/macOS 用 /)。os.path 仅在维护老代码时才需要。
Path 对象基础
创建 Path
from pathlib import Path
p1 = Path('hello.txt') # 相对路径
p2 = Path('/home/user/docs') # 绝对路径
p3 = Path() # 当前目录
p4 = Path.home() # 用户主目录,如 /home/tom
p5 = Path.cwd() # 当前工作目录
# Windows 上也能正常工作
win_path = Path('C:/Users/Tom/Documents')
print(win_path) # C:\Users\Tom\Documents
/ 运算符拼接路径
Path 重载了 / 运算符,可以像拼接字符串一样拼接路径,但语义更清晰:
base = Path('/home/user')
docs = base / 'docs'
readme = docs / 'readme.txt'
# 等价于
readme = Path('/home/user') / 'docs' / 'readme.txt'
常用属性
p = Path('/home/user/docs/readme.txt')
print(p.name) # 'readme.txt' 文件名(含扩展名)
print(p.stem) # 'readme' 文件名(不含扩展名)
print(p.suffix) # '.txt' 扩展名
print(p.suffixes) # ['.txt'] 所有扩展名(如 '.tar.gz' → ['.tar', '.gz'])
print(p.parent) # '/home/user/docs' 父目录
print(p.parts) # ('/', 'home', 'user', 'docs', 'readme.txt')
修改路径
p = Path('/home/user/docs/readme.txt')
# 修改文件名
print(p.with_name('intro.md')) # /home/user/docs/intro.md
print(p.with_suffix('.md')) # /home/user/docs/readme.md
# Python 3.12+ 新增方法
print(p.with_stem('intro')) # /home/user/docs/intro.txt
print(p.with_parent('/tmp')) # /tmp/readme.txt
读写文件
Path 对象直接提供了便捷的读写方法,无需再用 open():
from pathlib import Path
p = Path('note.txt')
# 一次写入(覆盖)
p.write_text('你好,世界\n', encoding='utf-8')
# 一次读取
content = p.read_text(encoding='utf-8')
print(content) # 你好,世界
# 二进制读写
p.write_bytes(b'\x89PNG\r\n\x1a\n')
data = p.read_bytes()
print(data) # b'\x89PNG\r\n\x1a\n'
read_text() 和 write_text() 是一次性操作,会把整个文件读入/写入内存。只适合中小文件,大文件还是要用 open() 迭代。
判断文件类型与获取信息
from pathlib import Path
p = Path('/home/user/docs/readme.txt')
# 判断存在性和类型
p.exists() # 是否存在
p.is_file() # 是否是文件
p.is_dir() # 是否是目录
# 获取文件信息
print(p.stat().st_size) # 文件大小(字节)
print(p.stat().st_mtime) # 修改时间(时间戳)
创建与删除
创建目录
from pathlib import Path
p = Path('data/cache/logs')
# 创建单层目录
Path('new_folder').mkdir()
# 递归创建多层(类似 mkdir -p)
p.mkdir(parents=True, exist_ok=True)
# parents=True:允许创建多层
# exist_ok=True:目录已存在时不报错
mkdir() 默认 parents=False, exist_ok=False。如果目录已存在或父目录不存在,会抛出 FileExistsError / FileNotFoundError。实际开发中通常都加 parents=True, exist_ok=True。
删除文件和目录
# 删除文件
Path('temp.txt').unlink(missing_ok=True)
# missing_ok=True 是 3.8 新增:文件不存在时不报错
# 删除空目录
Path('empty_folder').rmdir()
# 删除非空目录:需要用 shutil
import shutil
shutil.rmtree('folder_with_files')
glob 与 rglob:查找文件
glob:当前层匹配
from pathlib import Path
# 当前目录下的所有 .txt 文件
for f in Path('.').glob('*.txt'):
print(f)
rglob:递归匹配
# 递归查找所有 .py 文件
for f in Path('.').rglob('*.py'):
print(f)
# 等价于 glob('**/*.py')
for f in Path('.').glob('**/*.py'):
print(f)
Path.glob() 返回的结果顺序是不确定的(取决于文件系统)。如果需要稳定顺序,请用 sorted(Path('.').glob('*.txt'))。
延伸阅读
本节介绍了 pathlib 的基础用法。如需深入了解 pathlib 的完整功能(包括 PurePath 体系、目录遍历、路径安全性、跨平台技巧等),请参阅:
pathlib 完整教程 — 涵盖 PurePath vs Path、Path.walk() 方法、Python 3.12 新特性、批量重命名实战等高级内容。
- pathlib 官方文档 - 完整 API 参考
- PEP 428 - pathlib 模块规范
✅ 本节总结
- 优先使用
pathlib.Path而非os.path,代码更短、跨平台、面向对象 - 路径拼接用
/运算符,访问属性用.name/.stem/.suffix/.parent - 小文件读写用
read_text()/write_text(),大文件用open()+ 迭代 - 判断存在用
exists(),判断类型用is_file()/is_dir() - 创建目录用
mkdir(parents=True, exist_ok=True),删除文件用unlink(missing_ok=True) - 查找文件用
glob()当前层,rglob()递归,结果未排序,需要排序用sorted()
🎯 动手练习
基础题
- 用
pathlib创建一个多层目录结构project/src/tests,然后用glob查找所有.py文件。 - 给定一个文件路径,用 pathlib 属性提取文件名、扩展名、父目录,并用
with_suffix将.txt改为.md。
进阶题
- 写一个函数,接收目录路径,递归统计该目录下所有文件的总大小(字节),并按大小降序返回前 10 个文件。
- 用 pathlib 实现一个简单的文件备份工具:比较源目录和目标目录,找出新增和修改的文件并复制过去。
下一章我们将学习如何在 Python 中读写 JSON——一种最流行的数据交换格式。