Skip to content

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.json

7.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()               # pathlib

pathlib的代码更简洁,可读性更好。新项目推荐用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最优雅的地方。