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

核心优势:

  1. 面向对象 (OO):路径是一个对象,所有操作都是该对象的方法(如 p.exists(), p.is_dir()),而不是零散的函数(如 os.path.exists(p), os.path.isdir(p))。
  2. 可读性强:使用 / 重载操作符来拼接路径,比 os.path.join() 更自然。
  3. 跨平台:你只需要使用 /pathlib 会自动在 Windows 上将其转换为 \,在 Linux/macOS 上保持为 /
  4. 功能集成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.globos.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('*')
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐