python-pathlib中Path的使用
from pathlib import Path 是 Python 3.4+ 引入的一个非常强大的标准库 pathlib 中的核心类。它的目标是使用面向对象的方式来处理文件系统路径,从而取代(或者说极大改善)了老旧的、基于字符串操作的 os.path 模块。
Path 对象是一个代表了文件系统路径的对象,而不是一个简单的字符串。这个对象上挂载了许多便捷的方法,让路径的拼接、解析、文件操作、遍历等变得极其优雅和易读。
下面是对 Path 用法的详细介绍,分为几个核心部分:
1. 为什么使用 pathlib.Path?
在 pathlib 出现之前,我们通常使用 os.path 来处理路径,代码可能长这样:
Python
import os
# 路径拼接
config_dir = 'settings'
config_file = 'config.ini'
full_path = os.path.join(os.path.expanduser('~'), config_dir, config_file)
# 检查文件是否存在
if os.path.exists(full_path):
# 读取文件
with open(full_path, 'r') as f:
content = f.read()
使用 pathlib.Path,代码变得更加简洁和直观:
Python
from pathlib import Path
# 路径拼接使用 / 操作符
config_file = Path.home() / 'settings' / 'config.ini'
# 检查和读取
if config_file.exists():
content = config_file.read_text(encoding='utf-8')
核心优势:
- 面向对象 (OO):路径是一个对象,所有操作都是该对象的方法(如
p.exists(),p.is_dir()),而不是零散的函数(如os.path.exists(p),os.path.isdir(p))。 - 可读性强:使用
/重载操作符来拼接路径,比os.path.join()更自然。 - 跨平台:你只需要使用
/,pathlib会自动在 Windows 上将其转换为\,在 Linux/macOS 上保持为/。 - 功能集成:
Path对象集成了os,os.path,glob甚至shutil中的许多常用功能。
2. 创建 Path 对象
创建 Path 对象非常简单。
Python
from pathlib import Path
# 1. 传入一个或多个字符串
p1 = Path('path/to/my/file.txt')
p2 = Path('path', 'to', 'my', 'file.txt') # 效果同上,会自动拼接
print(p1) # 输出: path/to/my/file.txt (或 Windows 上的 path\to\my\file.txt)
# 2. 获取特殊路径
p_cwd = Path.cwd() # 获取当前工作目录 (Current Working Directory)
p_home = Path.home() # 获取当前用户的主目录
print(p_cwd)
print(p_home)
# 3. 获取当前文件路径 (非常常用)
# __file__ 是 Python 中的一个内置变量,代表当前脚本文件的路径
p_file = Path(__file__)
p_dir = Path(__file__).parent # 获取当前文件所在的目录
3. 路径拼接与操作
这是 pathlib 最具革命性的功能。
3.1. 路径拼接 (使用 / )
Path 对象重载了 / 操作符,用于拼接路径。
Python
# 假设 p_home 是 /Users/username (或 C:\Users\username)
p_home = Path.home()
# 拼接子目录和文件
docs_path = p_home / 'Documents'
report_path = docs_path / 'reports' / '2025_report.pdf'
print(report_path)
# 输出: /Users/username/Documents/reports/2025_report.pdf
# (或 Windows: C:\Users\username\Documents\reports\2025_report.pdf)
3.2. 访问路径的各个部分
Path 对象提供了丰富的属性来获取路径的元信息。
假设我们有这样一个路径:
p = Path(‘/usr/local/share/doc/python-3.10.tar.gz’)
Python
p = Path('/usr/local/share/doc/python-3.10.tar.gz')
# .parent: 获取父目录
print(p.parent) # /usr/local/share/doc
# .name: 获取路径的最后一部分 (文件名或目录名)
print(p.name) # python-3.10.tar.gz
# .stem: 获取文件名 (不含最后一个后缀)
print(p.stem) # python-3.10.tar
# .suffix: 获取最后一个后缀 (带.)
print(p.suffix) # .gz
# .suffixes: 获取所有后缀的列表
print(p.suffixes) # ['.tar', '.gz']
# .parts: 将路径分割成一个元组
print(p.parts)
# ('/', 'usr', 'local', 'share', 'doc', 'python-3.10.tar.gz')
# .anchor: 获取路径的 "锚点" (根目录或驱动器)
print(p.anchor) # /
print(Path('C:/Windows').anchor) # C:\
3.3. 路径解析
Python
# .resolve(): 获取绝对路径,并解析所有符号链接 (symlinks)
# 这是一个非常可靠的获取完整真实路径的方法
p = Path('../relative/path')
abs_path = p.resolve()
print(abs_path)
# .absolute(): 也可以获取绝对路径 (但不解析符号链接)
# print(p.absolute())
# .is_absolute(): 判断是否是绝对路径
print(p.is_absolute()) # False
print(abs_path.is_absolute()) # True
4. 文件和目录操作 (I/O)
Path 对象提供了直接读写、创建和删除文件/目录的方法。
4.1. 检查状态
Python
p = Path('my_file.txt')
p.exists() # 检查路径是否存在 (文件或目录)
p.is_file() # 检查是否是一个文件
p.is_dir() # 检查是否是一个目录
p.is_symlink() # 检查是否是一个符号链接
4.2. 读写文件 (极大简化)
这组方法是 pathlib 的一大亮点,对于简单的文件读写,不再需要 with open(...)。
Python
p_text = Path('greeting.txt')
p_bin = Path('data.bin')
# 写文本 (自动处理 'w' 模式和 'utf-8' 编码)
p_text.write_text('Hello, world!', encoding='utf-8')
# 读文本 (自动处理 'r' 模式和 'utf-8' 编码)
content = p_text.read_text(encoding='utf-8')
print(content) # "Hello, world!"
# 写二进制数据
p_bin.write_bytes(b'\x01\x02\x03')
# 读二进制数据
data = p_bin.read_bytes()
print(data) # b'\x01\x02\x03'
# 如果你需要更复杂的操作 (如追加、逐行读),仍然可以使用 .open()
with p_text.open('a', encoding='utf-8') as f:
f.write('\nAppended line.')
4.3. 创建和删除
Python
# --- 创建 ---
# 创建一个空文件 (类似 Linux 的 touch 命令)
p_file = Path('empty.txt')
p_file.touch(exist_ok=True) # exist_ok=True 表示如果文件已存在,不报错
# 创建一个目录
p_dir = Path('my_directory')
p_dir.mkdir(exist_ok=True) # exist_ok=True 类似 mkdir -p
# 递归创建多层目录 (非常有用!)
p_nested_dir = Path('a/b/c')
p_nested_dir.mkdir(parents=True, exist_ok=True) # parents=True 类似 mkdir -p
# --- 删除 ---
# 删除文件
p_file.unlink(missing_ok=True) # missing_ok=True 表示如果文件不存在,不报错
# 删除一个空目录
p_dir.rmdir()
# 注意: rmdir() 只能删除空目录。
# 删除一个非空目录 (及其所有内容)
# pathlib 本身不直接提供递归删除 (如 rm -rf),
# 你仍然需要使用 shutil 库,但 Path 对象可以作为参数传入
import shutil
shutil.rmtree(p_nested_dir)
4.4. 重命名和移动
Python
p = Path('old_name.txt')
p.touch()
# 重命名 (在同一目录下)
p.rename('new_name.txt')
# 移动并重命名
p_target = Path('archive/2025/moved_name.txt')
p_target.parent.mkdir(parents=True, exist_ok=True) # 确保目标目录存在
Path('new_name.txt').rename(p_target)
5. 路径遍历与搜索 (Glob)
pathlib 极大地简化了目录内容的遍历和文件搜索,取代了 glob.glob 和 os.walk 的部分功能。
假设我们有如下目录结构:
project/
├── main.py
├── utils/
│ ├── __init__.py
│ └── helper.py
├── data/
│ ├── sales.csv
│ └── internal/
│ └── report.csv
└── README.md
Python
p = Path('project')
# 1. 遍历目录 (p.iterdir()) - 非递归
# 只遍历 'project' 下的一级内容
print("--- iterdir() ---")
for item in p.iterdir():
if item.is_file():
print(f"File: {item.name}")
elif item.is_dir():
print(f"Dir: {item.name}")
# 输出:
# Dir: utils
# File: main.py
# File: README.md
# Dir: data
# 2. 搜索文件 (p.glob()) - 非递归
# 查找 'project' 目录下的所有 .py 文件
print("--- glob('*.py') ---")
for py_file in p.glob('*.py'):
print(py_file) # project/main.py
# 3. 递归搜索 (p.rglob()) - Recursive Glob
# 查找 'project' 及其所有子目录下的所有 .py 文件
print("--- rglob('*.py') ---")
for py_file in p.rglob('*.py'):
print(py_file)
# 输出:
# project/main.py
# project/utils/helper.py
# project/utils/__init__.py
# 查找所有 .csv 文件
print("--- rglob('*.csv') ---")
for csv_file in p.rglob('*.csv'):
print(csv_file)
# 输出:
# project/data/sales.csv
# project/data/internal/report.csv
总结
pathlib.Path 是 Python 现代编程中处理文件系统的标准和首选方式。它通过一个干净、统一的面向对象接口,将路径操作、文件 I/O、状态检查和目录遍历等功能整合在一起,使得代码更简洁、更健壮、更易于阅读和维护。
从 os.path 迁移过来的关键转变:
| 传统 os.path | 现代 pathlib.Path |
|---|---|
os.path.join(a, b) | Path(a) / b |
os.path.exists(p) | Path(p).exists() |
os.path.isdir(p) | Path(p).is_dir() |
os.path.abspath(p) | Path(p).resolve() (更推荐) |
os.path.basename(p) | Path(p).name |
os.path.dirname(p) | Path(p).parent |
os.path.splitext(p)[0] | Path(p).stem |
os.path.splitext(p)[1] | Path(p).suffix |
open(p, 'r') | Path(p).read_text() |
open(p, 'w') | Path(p).write_text(...) |
os.makedirs(p, exist_ok=True) | Path(p).mkdir(parents=True, exist_ok=True) |
os.remove(p) | Path(p).unlink() |
glob.glob(p + '/*.txt') | Path(p).glob('*.txt') |
os.walk(p) | (对于简单递归) Path(p).rglob('*') |
更多推荐


所有评论(0)