05 pathlib现代路径
os.path能做的事情,pathlib都能做,而且写起来更简洁。pathlib把路径封装成对象,用斜杠/拼接路径,用方法代替函数调用,代码读起来更自然。
Python 3.4引入了pathlib,现在它已经是处理路径的推荐方式。
一、创建路径对象
1.1 Path类
python
from pathlib import Path
# 创建路径对象
p = Path("data/file.txt")
# 当前目录
p = Path(".")
# 用户主目录
p = Path.home()
# PosixPath('/Users/apple')
# 当前工作目录
p = Path.cwd()
# PosixPath('/Users/apple/project')1.2 斜杠拼接路径
pathlib最爽的地方是用斜杠/拼接路径:
python
from pathlib import Path
p = Path("data")
# 用/拼接路径
filepath = p / "config" / "settings.json"
# PosixPath('data/config/settings.json')
# 也可以和字符串拼接
filepath = p / "file.txt"这比os.path.join("data", "config", "settings.json")简洁多了。
1.3 跨平台
pathlib自动处理平台差异:
python
from pathlib import Path, PureWindowsPath, PurePosixPath
# 自动使用当前平台的路径风格
p = Path("data/file.txt")
# Linux/macOS: PosixPath('data/file.txt')
# Windows: WindowsPath('data/file.txt')
# 显式指定平台(纯计算,不涉及IO)
p = PureWindowsPath("data/file.txt")
# WindowsPath('data/file.txt')
p = PurePosixPath("data/file.txt")
# PosixPath('data/file.txt')二、路径属性
2.1 基本属性
python
from pathlib import Path
p = Path("/Users/apple/project/data.tar.gz")
p.name # 'data.tar.gz' (完整文件名)
p.stem # 'data.tar' (不含最后一个扩展名)
p.suffix # '.gz' (最后一个扩展名)
p.suffixes # ['.tar', '.gz'] (所有扩展名)
p.parent # PosixPath('/Users/apple/project') (父目录)
p.anchor # '/' (根锚点)
p.parts # ('/', 'Users', 'apple', 'project', 'data.tar.gz')2.2 父目录链
python
from pathlib import Path
p = Path("/Users/apple/project/data/file.txt")
p.parent # /Users/apple/project/data
p.parent.parent # /Users/apple/project
# 遍历所有父目录
for parent in p.parents:
print(parent)
# /Users/apple/project/data
# /Users/apple/project
# /Users/apple
# /Users
# /2.3 路径判断
python
from pathlib import Path
p = Path("/Users/apple/data.txt")
p.is_absolute() # True
p.is_relative_to("/Users/apple") # True (3.9+)
# 转换为字符串
str(p) # '/Users/apple/data.txt'
p.as_posix() # '/Users/apple/data.txt' (POSIX风格)
p.as_uri() # 'file:///Users/apple/data.txt' (URI格式)三、路径修改
3.1 替换文件名
python
from pathlib import Path
p = Path("/Users/apple/data.txt")
# 替换完整文件名
p.with_name("config.json")
# PosixPath('/Users/apple/config.json')
# 替换文件名(不含扩展名)
p.with_stem("result")
# PosixPath('/Users/apple/result.txt')
# 替换扩展名
p.with_suffix(".json")
# PosixPath('/Users/apple/data.json')
# 去掉扩展名
p.with_suffix("")
# PosixPath('/Users/apple/data')3.2 相对路径计算
python
from pathlib import Path
p = Path("/Users/apple/project/data/file.txt")
# 计算相对于某个目录的路径
p.relative_to("/Users/apple/project")
# PosixPath('data/file.txt')
# 检查是否是相对路径
p.is_relative_to("/Users/apple") # True
p.is_relative_to("/tmp") # False四、路径检查
4.1 存在性检查
python
from pathlib import Path
p = Path("data.txt")
p.exists() # True 或 False
p.is_file() # True(是文件)
p.is_dir() # False(不是目录)
p.is_symlink() # False(不是符号链接)4.2 文件信息
python
from pathlib import Path
p = Path("data.txt")
# 文件状态
stat = p.stat()
stat.st_size # 文件大小
stat.st_mtime # 修改时间
stat.st_atime # 访问时间
# 文件大小
p.stat().st_size
# 文件所有者(Unix)
p.owner() # 'apple'
p.group() # 'staff'五、文件读写
pathlib最方便的地方是可以直接读写文件,不需要open():
5.1 读取文件
python
from pathlib import Path
p = Path("data.txt")
# 读取文本内容
content = p.read_text(encoding="utf-8")
# 读取二进制内容
data = p.read_bytes()5.2 写入文件
python
from pathlib import Path
p = Path("output.txt")
# 写入文本
p.write_text("Hello, Agent!", encoding="utf-8")
# 写入二进制
p.write_bytes(b"\x00\x01\x02")5.3 打开文件
python
from pathlib import Path
p = Path("data.txt")
# 用open()方法打开
with p.open("r", encoding="utf-8") as f:
content = f.read()
with p.open("w", encoding="utf-8") as f:
f.write("Hello")六、目录操作
6.1 创建目录
python
from pathlib import Path
p = Path("data/2026/06")
# 创建目录(可以递归创建)
p.mkdir(parents=True, exist_ok=True)
# parents=True: 递归创建父目录
# exist_ok=True: 目录已存在时不报错
# 创建单级目录
Path("logs").mkdir()6.2 删除文件/目录
python
from pathlib import Path
# 删除文件
Path("data.txt").unlink()
Path("data.txt").unlink(missing_ok=True) # 文件不存在时不报错
# 删除空目录
Path("empty_dir").rmdir()6.3 重命名/移动
python
from pathlib import Path
# 重命名
Path("old.txt").rename("new.txt")
# 移动(rename也可以移动)
Path("data.txt").rename("archive/data.txt")
# 强制覆盖目标
Path("new.txt").replace("old.txt")6.4 创建符号链接
python
from pathlib import Path
# 创建符号链接
Path("link.txt").symlink_to("original.txt")
# 创建硬链接
Path("hardlink.txt").hardlink_to("original.txt")七、遍历目录
7.1 iterdir()
遍历目录下的直接子项:
python
from pathlib import Path
p = Path("data")
# 遍历目录
for item in p.iterdir():
if item.is_file():
print(f"文件: {item.name}")
elif item.is_dir():
print(f"目录: {item.name}")7.2 glob() / rglob()
通配符搜索:
python
from pathlib import Path
p = Path("project")
# glob():在当前目录搜索
list(p.glob("*.py")) # 所有.py文件
list(p.glob("test_*.py")) # test_开头的.py文件
# rglob():递归搜索所有子目录
list(p.rglob("*.py")) # 所有子目录下的.py文件
list(p.rglob("**/*.py")) # 等价写法
# 复杂模式
list(p.glob("**/*.py")) # 所有Python文件
list(p.glob("*/config.json")) # 一级子目录下的config.json7.3 遍历所有文件
python
from pathlib import Path
def all_files(directory, pattern="*"):
"""递归获取所有匹配的文件"""
return sorted(Path(directory).rglob(pattern))
# 获取所有Python文件
py_files = all_files(".", "*.py")
# 获取所有图片
images = all_files("assets", "*.png")八、实用技巧
8.1 相对于脚本位置
python
from pathlib import Path
# 获取当前脚本所在目录
SCRIPT_DIR = Path(__file__).parent
# 相对于脚本位置读取配置
config_path = SCRIPT_DIR / "config.json"
config = config_path.read_text()8.2 安全地创建目录
python
from pathlib import Path
def ensure_dir(path):
"""确保目录存在"""
Path(path).mkdir(parents=True, exist_ok=True)
ensure_dir("data/2026/06")8.3 遍历并过滤文件
python
from pathlib import Path
# 获取所有Python文件,排除__pycache__
py_files = [
f for f in Path(".").rglob("*.py")
if "__pycache__" not in str(f)
]8.4 复制文件
python
import shutil
from pathlib import Path
src = Path("data.txt")
dst = Path("backup/data.txt")
# 复制文件
shutil.copy2(src, dst)
# 或者用pathlib + shutil
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(src, dst)8.5 获取临时目录
python
import tempfile
from pathlib import Path
# 临时目录
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
(tmp / "data.txt").write_text("临时数据")
# 退出with块后自动清理九、与os.path对比
同样的操作,两种写法:
python
# 拼接路径
os.path.join("data", "file.txt") # os.path
Path("data") / "file.txt" # pathlib
# 获取文件名
os.path.basename(path) # os.path
Path(path).name # pathlib
# 获取扩展名
os.path.splitext(path)[1] # os.path
Path(path).suffix # pathlib
# 检查存在
os.path.exists(path) # os.path
Path(path).exists() # pathlib
# 读取文件
open(path).read() # 传统
Path(path).read_text() # pathlibpathlib的代码更简洁,可读性更好。新项目推荐用pathlib,老代码可以继续用os.path。
十、总结
pathlib是处理路径的现代方式:
| 分类 | 常用操作 |
|---|---|
| 创建 | Path(), Path.home(), Path.cwd() |
| 拼接 | / 运算符 |
| 属性 | name, stem, suffix, parent, parts |
| 修改 | with_name(), with_stem(), with_suffix(), relative_to() |
| 检查 | exists(), is_file(), is_dir(), is_symlink() |
| 读写 | read_text(), read_bytes(), write_text(), write_bytes() |
| 目录 | mkdir(), unlink(), rmdir(), rename(), iterdir(), glob(), rglob() |
如果只能记住一个特性,那就是斜杠拼接路径:Path("data") / "file.txt"。这是pathlib最优雅的地方。