第 22 课 · 进阶 · 19 分钟

Python pathlib 路径

把文件路径当作对象,而不是容易出错的字符串。

pathlib文件路径后缀UTF-8 文本

昨天的收据放在一个每天换名字的文件夹里。字符串路径一碰到反斜杠就断,Path 对象不会。怎么列文件才不用猜分隔符?

pathlib 模块把路径变成一个带有属性和方法的对象。它能处理 Windows 与 POSIX 的分隔符,避免大多数字符串拼接错误,还能用一行代码读写小型文本文件。 你还会替换路径的单个部分、稳定地列出文件,并拒绝目录穿越。

用 / 拼接路径

斜杠运算符在这里不是除法,而是拼接路径。Path 重载了 /,让各部分连起来。每一段保持普通字符串即可,具体分隔符交给 pathlib 根据操作系统决定。

from pathlib import Path
path = Path("data") / "scores.csv"
print(path.as_posix())
print(path.name)

不靠字符串加法拼路径

查看路径的各个部分

name 是最后一段,stem 是去掉最后一个后缀的文件名,suffix 包含点号。parent 返回所在目录。这些属性比一串 split 调用更好读。

from pathlib import Path
path = Path("reports/2026-summary.txt")
print(path.stem)
print(path.suffix)
print(path.parent.as_posix())

文件名、后缀与父目录

读写 UTF-8 文本

write_text 会创建或覆盖文件,read_text 返回文件内容。显式传入 encoding='utf-8',结果就不会随机器区域设置变化。示例结束后记得清理临时文件。

from pathlib import Path
path = Path("pypractice-note.txt")
path.write_text("hello\n", encoding="utf-8")
print(path.read_text(encoding="utf-8").strip())
path.unlink()

一个小文本文件

只替换一个部分,不要拼接字符串

with_name 和 with_suffix 只替换一个组成部分,保留其余路径。它们比在整个字符串上做 replace() 安全,因为不会误改目录名。Path 本身不可变,每次调用都会返回新对象。

from pathlib import Path
path = Path("reports/2026-summary.txt")
print(path.with_name("2027-summary.txt").as_posix())
print(path.with_suffix(".md").as_posix())
print((path.parent / "archive" / path.name).as_posix())

替换名称、后缀或父目录

稳定地列出文件

glob() 返回的是文件系统顺序,并不保证已排序。展示结果或比较结果前要先排序。TemporaryDirectory 给示例一个私有目录,即使代码块异常退出也会清理。

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as tmp:
    root = Path(tmp)
    (root / "b.txt").write_text("tea", encoding="utf-8")
    (root / "a.txt").write_text("latte", encoding="utf-8")
    (root / "skip.md").write_text("x", encoding="utf-8")
    for path in sorted(root.glob("*.txt")):
        print(path.name, path.read_text(encoding="utf-8"))

排序 glob 的结果,而不是相信文件系统

表单值不是安全路径

Path(raw).name 只保留最后一段,因此 ../secret.txt 不能从这一层直接逃出目录。这只是起点,不是完整的安全策略:还要使用允许列表、解析最终路径,并确认它仍在目标根目录内,再打开文件。

from pathlib import Path
for raw in ["notes.txt", "../secret.txt", "/etc/passwd"]:
    safe_name = Path(raw).name
    print(raw, "->", safe_name)

拼接前先去掉目录部分

本课要点

  • Path('folder') / 'file.txt' 可以安全地拼接路径。
  • name、stem、suffix 和 parent 分别暴露路径的不同部分。
  • 不传 encoding 时,read_text 和 write_text 使用平台默认编码。
  • 输出必须始终使用正斜杠时,用 as_posix()。
  • 路径组成部分用 Path 方法处理;不要把不可信文本直接拼到根目录后面。

常见错误

  • 用字符串 + 拼路径,却忘记补分隔符。
  • 需要稳定、可移植的字符串时,直接打印 Path 对象。
  • 读写文本时不指定 UTF-8。
  • 对整个路径调用 replace(),误改了父目录名。
轮到你

创建 Path('data') / 'scores.csv',打印它的 name、suffix,以及用 POSIX 形式表示的 parent。

动手试试

改改变量、先预测输出,再运行代码。第一次点击“运行代码”时会下载 Python 运行时,可能需要几秒钟。

浏览器内 Python本地运行 · 无需账号
首次运行会从 CDN 下载 Pyodide。修改后点击“运行代码”。

练习本课

12 道题,作答后立即看到解释。

查看 12 道题答案开始练习
← enumerate 与 zip日期与时间 →