跳到主要内容

我们必须知道,我们终将知道。

David Hilbert数学公理化之父

📂 路径处理

pathlib 是 Python 处理文件路径的现代工具,提供面向对象、跨平台的路径处理 API。

📌 本节要点

  • pathlib 优先:新项目推荐 Path 对象,代码更短、跨平台、面向对象
  • / 运算符:路径拼接,比 os.path.join 更直观
  • 属性访问.name / .stem / .suffix / .parent 替代 os.path.basename 等函数
  • 小文件读写read_text() / write_text() 一行搞定 :::
pathlib 快速体验

os.path vs pathlib

传统的 os.path 把路径当作字符串,所有操作都是函数调用:

Python
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 对象,操作更直观、更链式:

Python
from pathlib import Path

# 现代写法:面向对象,跨平台
base = Path('/home/user')
full = base / 'docs' / 'readme.txt'
name = full.name
parent = full.parent
exists = full.exists()
推荐使用 pathlib

对于新项目,强烈推荐使用 pathlib:代码更短、可读性更好、自动处理平台差异(Windows 用 \,Linux/macOS 用 /)。os.path 仅在维护老代码时才需要。

Path 对象基础

创建 Path

Python
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 重载了 / 运算符,可以像拼接字符串一样拼接路径,但语义更清晰:

Python
base = Path('/home/user')
docs = base / 'docs'
readme = docs / 'readme.txt'

# 等价于
readme = Path('/home/user') / 'docs' / 'readme.txt'

常用属性

Python
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')

修改路径

Python
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()

Python
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() 迭代。

判断文件类型与获取信息

Python
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) # 修改时间(时间戳)

创建与删除

创建目录

Python
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

删除文件和目录

Python
# 删除文件
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:当前层匹配

Python
from pathlib import Path

# 当前目录下的所有 .txt 文件
for f in Path('.').glob('*.txt'):
print(f)

rglob:递归匹配

Python
# 递归查找所有 .py 文件
for f in Path('.').rglob('*.py'):
print(f)

# 等价于 glob('**/*.py')
for f in Path('.').glob('**/*.py'):
print(f)
glob 结果未排序

Path.glob() 返回的结果顺序是不确定的(取决于文件系统)。如果需要稳定顺序,请用 sorted(Path('.').glob('*.txt'))

延伸阅读

本节介绍了 pathlib 的基础用法。如需深入了解 pathlib 的完整功能(包括 PurePath 体系、目录遍历、路径安全性、跨平台技巧等),请参阅:

深入学习 pathlib

pathlib 完整教程 — 涵盖 PurePath vs PathPath.walk() 方法、Python 3.12 新特性、批量重命名实战等高级内容。

✅ 本节总结

  • 优先使用 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()

🎯 动手练习

基础题

  1. pathlib 创建一个多层目录结构 project/src/tests,然后用 glob 查找所有 .py 文件。
  2. 给定一个文件路径,用 pathlib 属性提取文件名、扩展名、父目录,并用 with_suffix.txt 改为 .md

进阶题

  1. 写一个函数,接收目录路径,递归统计该目录下所有文件的总大小(字节),并按大小降序返回前 10 个文件。
  2. 用 pathlib 实现一个简单的文件备份工具:比较源目录和目标目录,找出新增和修改的文件并复制过去。

下一章我们将学习如何在 Python 中读写 JSON——一种最流行的数据交换格式。