pathlib:别再手写路径拼接了
用标准库 pathlib.Path 替代 os.path 和字符串拼接:/ 运算符、读写文件、mkdir、exists 与常见踩坑,示例在 Python 3.13 验证。
要解决的问题
写 Python 后端脚本时,路径几乎绕不开:配置文件在哪、日志写到哪、上传目录怎么拼、临时文件落在何处。很多人习惯 os.path.join("a", "b", "c"),或者直接 "a" + "/" + "b"。在 Linux 上往往能跑通,一到 Windows、或脚本换了工作目录,就开始出现少斜杠、多斜杠、编码乱码这类问题。
标准库模块 pathlib 从 Python 3.4 起就在了。它把路径当成对象来用:用 / 运算符拼接,用方法读写文本、创建目录、判断文件是否存在。新脚本里优先用 Path,可读性和跨平台都会稳一些。本文示例已在本机 Python 3.13.5 验证;3.12 及以上 同样适用。
核心概念
先记住日常最常用的几个点:
from pathlib import Path:多数情况只需要Path这一个类。它会实例化当前系统对应的具体路径(POSIX 上是PosixPath,Windows 上是WindowsPath)。- 拼接:
base / "data" / "logs",或base.joinpath("data", "logs"),语义接近os.path.join,但不用自己管分隔符。 - 拆解:
.name是最后一段文件名,.stem去掉最后后缀后的主名,.suffix是最后一段后缀(如.log),.parent是父目录。 - 读写:
read_text/write_text一次读写整个文本文件;请始终写上encoding="utf-8"。 - 判断:
.exists()、.is_file()、.is_dir()。 - 建目录:
mkdir(parents=True, exist_ok=True),效果类似 shell 的mkdir -p。 - 绝对化:
resolve()会得到绝对路径,并尽量展开符号链接。 - 列举:
iterdir()列出直接子项;glob("*.py")按模式匹配(可用**做递归,见官方文档)。
完整 API 与版本说明见官方文档:pathlib — Object-oriented filesystem paths。设计动机见 PEP 428。
示例代码
下面是一段可直接粘贴的日常写法(思路与本文本地验证一致):
from pathlib import Path
base = Path("/tmp/demo-app")
log_dir = base / "var" / "log" # 等同 base.joinpath("var", "log")
log_dir.mkdir(parents=True, exist_ok=True)
log = log_dir / "app.log"
log.write_text("你好 pathlib\n", encoding="utf-8")
text = log.read_text(encoding="utf-8")
print(text) # 你好 pathlib
print(log.name) # app.log
print(log.stem) # app
print(log.suffix) # .log
print(log.parent) # .../var/log
assert log.exists() and log.is_file()
assert log_dir.is_dir()
print(log.resolve()) # 绝对路径
# 列目录与简单 glob
for child in sorted(log_dir.iterdir()):
print("child:", child.name)
print(list(log_dir.glob("*.log")))
关于「修改路径」:Path 对象本身是不可变的。写 p /= "subdir" 时,是把变量 p 重新绑定到新的 Path,并不是原地改原来那个对象。需要备份文件名时,不要写 path + ".bak"(会 TypeError),可以:
bak = log.parent / (log.name + ".bak")
# 或
bak = log.with_name(log.name + ".bak")
传给只接受字符串的老接口时,用 str(path) 或 os.fspath(path)。多数接受路径的现代 API 已支持 os.PathLike,可以直接传 Path。
常见误区
-
用
+把Path和字符串硬拼
Path("/tmp/a") + "/b"会直接类型错误。拼接请用/或joinpath。 -
读写文本不指定编码
encoding默认跟平台 locale 走。在 Linux 上碰巧是 UTF-8,到 Windows 就可能乱码。后端日志、配置、JSON 旁路文件,一律显式encoding="utf-8"。 -
把相对路径当成「相对脚本」
Path("data/out.txt")相对的是进程当前工作目录,不是.py文件所在目录。若要相对脚本定位资源,常见写法是:
Path(__file__).resolve().parent / "data" / "out.txt"。 -
忘记少数库只要
str
报「期望 str」时再转换即可;不要因此退回整段手写字符串路径。官方对比表也说明了pathlib与os.path的对应关系,见文档中的 Comparison to the os and os.path modules。 -
为了「跨平台」自己拼
/和\\
交给Path:它会按当前系统处理分隔符。需要在 Unix 上操作 Windows 风格路径字符串时,才考虑PureWindowsPath这类纯路径类(一般业务代码用不到)。 -
mkdir参数没配对
只写mkdir()时,父目录不存在会报错,目录已存在也会报错。一次性建多级且允许已存在,请用parents=True, exist_ok=True。
小结
新写的 Python 后端脚本,路径处理优先用 pathlib.Path:用 / 拼接,用 read_text/write_text 并固定 UTF-8,用 mkdir(parents=True, exist_ok=True) 建目录,用 exists/is_file/is_dir 判断,需要规范绝对路径时再调用 resolve(),列举用 iterdir/glob。os.path 没有过时,底层或兼容旧代码时仍会用到;但不必再靠字符串加斜杠来拼日常路径。养成「路径是对象」的习惯,跨平台和可读性都会轻松不少。
参考资料
谢谢你读到这里。