61人参与 • 2026-10-11 • Python
在 python 3.4 之前,路径操作几乎全靠 os.path 模块里那些面向字符串的函数:os.path.join()、os.path.basename()、os.path.exists()……代码写起来冗长,跨平台还得时刻操心分隔符。pathlib 的诞生彻底改变了这一切:它用面向对象的方式封装了路径,用 / 运算符拼接路径,用 .read_text() 读写文件,用 .glob() 搜索文件,代码变得简洁而富有表现力。然而,从 os.path 迁移到 pathlib 并非无痛——.resolve() 会访问文件系统、purepath 与 path 的区别容易混淆、glob 的行为细节与 glob 模块不尽相同、跨平台大小写敏感性依然存在。今天,我们就来彻底解剖 pathlib 的设计哲学、核心用法和那些让人栽跟头的陷阱,让你真正驾驭这个现代路径操作利器。

from pathlib import path
p = path('nonexistent/file.txt')
print(p.resolve())
# 输出:/current/working/dir/nonexistent/file.txt
.resolve() 在文件不存在时不会报错,而是基于当前工作目录和已存在的最长前缀进行规范化。如果你以为它会检查文件是否存在,就会误判。更危险的是,在 python 3.6 之前,resolve() 在路径不存在时会抛出 filenotfounderror,行为在不同版本间发生了变化。
from pathlib import path
base = path('/data')
filename = 'file.txt'
path = base + '/' + filename # typeerror: unsupported operand type(s) for +: 'posixpath' and 'str'
path 不支持与字符串直接用 + 拼接,必须使用 / 运算符或 os.path.join。很多从字符串迁移过来的开发者会下意识地使用 +,结果立刻报错。
from pathlib import pureposixpath, path
pure = pureposixpath('/data/file.txt')
print(pure.exists()) # attributeerror: 'pureposixpath' object has no attribute 'exists'
purepath 只提供纯粹的路径操作(拼接、分解、判断后缀等),不涉及文件系统 i/o。path 继承自 purepath,添加了 exists()、read_text()、glob() 等 i/o 方法。如果你只需要路径运算,应使用 purepath;如果需要访问文件系统,才用 path。
from pathlib import path
# pathlib 的 glob 默认不包含隐藏文件(python 3.11 之前)
files = list(path('.').glob('*'))
# 而 glob 模块的 glob.glob('*') 也不包含隐藏文件,两者行为一致
# 但 pathlib 的 rglob 和 glob 模块的 recursive=true 在细节上可能有差异
更值得注意的是,pathlib 的 glob 在 python 3.11 之前不支持 include_hidden 参数,无法直接匹配隐藏文件,而 glob 模块可以通过 .* 模式匹配。python 3.11 引入了 include_hidden=true 参数来解决这个问题。
from pathlib import path
p = path('/data/file.txt')
print(p == '/data/file.txt') # false!
print(str(p) == '/data/file.txt') # true
path 对象与字符串比较永远返回 false,因为它不会自动进行类型转换。必须显式转换为字符串或使用 path 对象比较。
from pathlib import path
p1 = path('data/file.txt')
p2 = path('data/file.txt')
print(p1 == p2) # 在 windows 上:true(因为 windowspath 使用大小写不敏感的比较)
# 在 linux 上:false
path 的相等性在 windows 上不区分大小写,在 posix 上区分。这可能导致跨平台逻辑不一致。
from pathlib import path
path('output.txt').write_text('你好')
# 在 windows 上可能用 cp1252 编码,导致写入失败或乱码
与 open() 一样,path.write_text() 和 read_text() 默认使用系统编码。应显式指定 encoding='utf-8'。
purepath
├── pureposixpath
└── purewindowspath
path
├── posixpath
└── windowspath
purepath:纯路径操作,不访问文件系统。跨平台时可用 pureposixpath 或 purewindowspath 模拟特定平台行为。path:具体路径,根据当前操作系统自动实例化为 posixpath 或 windowspath,提供 i/o 方法。path('/data') / 'file.txt' 等价于 os.path.join('/data', 'file.txt'),但更直观。如果右操作数是绝对路径,左操作数会被丢弃:
path('/data') / '/etc/passwd' # pureposixpath('/etc/passwd')
| 属性/方法 | 说明 |
|---|---|
.name | 文件名(含后缀) |
.stem | 文件名(不含后缀) |
.suffix | 后缀(含点) |
.suffixes | 所有后缀列表 |
.parent | 父目录 |
.parents | 所有祖先目录序列 |
.parts | 路径各部分元组 |
.anchor | 根锚点(如 / 或 c:\) |
.exists() | 是否存在 |
.is_file() / .is_dir() | 类型判断 |
.resolve() | 绝对路径 + 符号链接解析 |
.absolute() | 绝对路径(不解析符号链接) |
.read_text() / .write_text() | 文本读写 |
.read_bytes() / .write_bytes() | 二进制读写 |
.mkdir() / .rmdir() | 创建/删除目录 |
.unlink() | 删除文件 |
.glob() / .rglob() | 模式匹配 |
.iterdir() | 遍历目录 |
.stat() | 文件状态 |
.touch() | 创建空文件或更新时间戳 |
strict=false,即路径不存在时不报错)。.. 和 .。strict=false 是默认值;strict=true 时路径不存在会抛出 filenotfounderror。os.fspath(path) 返回字符串路径。str(path) 返回字符串路径。path(os_path_str) 将字符串转为 path。os.path 函数通常也接受 path 对象。path.glob(pattern):在当前目录下匹配模式。path.rglob(pattern):递归匹配。include_hidden=true。path('/data') + '/file.txt' # typeerror
应使用 / 运算符。
path('/data') == '/data' # false
应使用 str(path) 或直接比较 path 对象。
purepath('/data').exists() # attributeerror
需要 i/o 时使用 path。
python 3.6 之前,resolve() 在路径不存在时抛出异常;之后默认 strict=false。如果你依赖旧行为,需显式 strict=true。
list(path('.').glob('*')) # 不包含 .hidden
解决方案:使用 os.listdir 或升级到 python 3.11+ 使用 include_hidden=true。
path('a/b/c').mkdir() # filenotfounderror
应使用 mkdir(parents=true, exist_ok=true)。
path('missing.txt').unlink() # filenotfounderror
python 3.8+ 支持 missing_ok=true。
p = path('c:/data/file.txt')
print(p) # c:\data\file.txt(windows 上自动转换)
path 会自动将 / 转为 \,但字符串表示在不同平台上不同。
默认编码因平台而异,应显式指定 encoding='utf-8'。
与 glob 模块不同,pathlib 的 glob 和 rglob 自动处理递归,** 在 glob 中也能工作(python 3.5+)。
from pathlib import path
base = path('/data')
file = base / 'subdir' / 'file.txt'
from pathlib import path
p = path('config.json')
if p.exists():
text = p.read_text(encoding='utf-8')
p.write_text('{"key": "value"}', encoding='utf-8')
path('a/b/c').mkdir(parents=true, exist_ok=true)
p = path('file.txt')
p.unlink(missing_ok=true) # python 3.8+
d = path('empty_dir')
try:
d.rmdir()
except filenotfounderror:
pass
for entry in path('.').iterdir():
if entry.is_file():
print(entry.name)
# 当前目录下的 .py 文件
for p in path('.').glob('*.py'):
print(p)
# 递归搜索
for p in path('.').rglob('*.py'):
print(p)
# python 3.11+ 包含隐藏文件
for p in path('.').glob('*', include_hidden=true):
print(p)
p = path('/data/reports/summary.csv')
print(p.name) # summary.csv
print(p.stem) # summary
print(p.suffix) # .csv
print(p.parent) # /data/reports
print(p.parts) # ('/', 'data', 'reports', 'summary.csv')
str(p) os.fspath(p)
import os
p = path('/data/file.txt')
os.path.exists(p) # 接受 path 对象
from pathlib import pureposixpath, purewindowspath
posix = pureposixpath('/data/file.txt')
windows = purewindowspath('c:/data/file.txt')
def safe_join(base, user_input):
base = path(base).resolve()
target = (base / user_input).resolve()
if base not in target.parents and target != base:
raise valueerror("路径越界")
return target
repr(path):查看路径的精确表示。.resolve() 和 .absolute() 对比:理解符号链接和相对路径的处理。.exists() 和 .is_file():确认路径类型。purepath 进行纯路径测试:避免 i/o 副作用。..、符号链接。pathlib 在 python 版本间的差异:如 missing_ok、include_hidden、resolve 的严格性。pathlib.path,抛弃 os.path 的字符串拼接。purepath,需要 i/o 时使用 path。encoding='utf-8'。mkdir 时使用 parents=true, exist_ok=true。unlink 时使用 missing_ok=true(python 3.8+)。path 与字符串比较需要转换。.resolve() 时明确 strict 参数。glob 和 rglob 返回生成器,大目录下 注意内存。include_hidden=true 匹配隐藏文件。pathlib 是 python 路径操作的现代化革命,它用面向对象的方式让路径处理变得优雅而安全。但正如任何强大的工具,它也有自己的脾气:purepath 和 path 的分工、resolve() 的隐式行为、glob 与 glob 模块的微妙差异、跨平台的大小写敏感性。理解这些细节,你就能在文件系统的海洋中精准导航,用 / 运算符轻松拼接路径,用 .read_text() 优雅读写文件,用 .rglob() 递归搜索目录。从今天起,请把 pathlib 作为你操作路径的首选工具,让那些繁琐的字符串拼接和平台判断成为历史。你的代码将因此更加清晰、健壮,真正实现“一次编写,处处运行”的理想。
以上就是深入剖析python pathlib面向对象路径操作的常见坑及解决方案的详细内容,更多关于python pathlib路径操作的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论