小白学 Python
AI 编程指南
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录关于本站联系方式隐私政策GitHub

全部课程

  1. 00为什么学 Python
  2. 01Python 安装与第一个程序
  3. 02基本数据类型与变量
  4. 03List 与 Tuple
  5. 04Dict 与 Set
  6. 05条件与循环
  7. 06函数
  8. 07迭代
  9. 08面向对象
  10. 09模块
  11. 10魔法方法
  12. 11枚举类
  13. 12元类 metaclass
  14. 13线程与进程
  15. 14正则表达式
  16. 15闭包
  17. 16装饰器
  18. 17代码可读性
  19. 18pathlib:现代化路径处理
  20. 19异常处理
  21. 20dataclass
  22. 21上下文管理器(with)
  23. 22async / await
  24. 23pyproject.toml + uv
  25. 24ruff:一站式代码检查
  26. 25pytest:测试框架
  27. 26日志 logging
  28. 27打包发布到 PyPI
  29. 28学完之后
Python 环境加载中…

pathlib:现代化路径处理

4 道练习题·预计 95 分钟·做对一题解锁下一段

完整通读本章 →

教学 01 / 23· 已读

pathlib 路径处理

各位有没有写过这样的代码?

Python· 在本地运行
import os

base_dir = os.path.dirname(os.path.abspath(__file__))
data_path = os.path.join(base_dir, 'data', 'sub', 'foo.txt')

if os.path.exists(data_path) and os.path.isfile(data_path):
    with open(data_path, 'r', encoding='utf-8') as f:
        content = f.read()
    print(content)

是不是看着头大?一个 os.path.dirname 套一个 os.path.abspath,再嵌一个 os.path.join,路径就这么一层一层包出来了。要打开还得 with open(...) as f:,要判断还得 os.path.exists 加 os.path.isfile,方法散落在 os 和 os.path 两个模块里,还要再加一个 open 内建函数。光是数函数名就数得我水哥头都晕。

更要命的是,路径在这套写法里只是个普通字符串。字符串就是字符串,它不知道自己代表的是文件还是目录,更不可能自己跑去判断「我存在吗」、「我是什么后缀」。所有这些操作都得拿着字符串去喂给一堆函数,函数再吐回字符串,字符串再传给下一个函数 …… 整个过程像极了车间里搬砖头的流水线。

那么有没有一种写法,让路径自己「活」起来呢?让 Path('data/foo.txt') 这种东西本身就知道自己是不是文件、能不能被读取、有什么后缀名?

有的,就是今天要聊的 pathlib。这是 Python 3.4 加进来的标准库,专门用来收拾上面这种乱糟糟的路径代码。从 Python 3.6 开始,标准库里大部分接受路径字符串的函数也都能直接吃 Path 对象,所以基本可以无痛切过来。

写到现在 Python 都 3.13 了,各位童鞋如果还在 os.path.join 一条道走到黑,那真的是亏大了。本文就跟着水哥一起,把 pathlib 这套现代 API 从头到尾捋一遍。

教学 02 / 23· 已读

一、第一个 Path

先来认识一下主角:

Python· 可在网页运行
from pathlib import Path

p = Path('data/foo.txt')
print(p)
print(type(p))

输出可能长这样(macOS / Linux 上):

文本
data/foo.txt
<class 'pathlib.PosixPath'>

是不是发现什么不对?我们明明是 Path('data/foo.txt'),怎么打印出来类型是 PosixPath?

这是因为 Path 是个聪明家伙,它会根据你当前的操作系统,自动给你返回对应平台的子类:

  • 在 macOS / Linux 上,返回 PosixPath
  • 在 Windows 上,返回 WindowsPath

各位平时基本不用关心这个,直接用 Path 就完事了,需要跨平台细节的时候再说。

除了 Path('字符串') 这种基础用法,还有两个非常常用的「快捷入口」:

Python· 在本地运行
from pathlib import Path

print(Path.home())
print(Path.cwd())

输出:

文本
/Users/two_water
/Users/two_water/projects/demo

Path.home() 是当前用户的家目录,Path.cwd() 是「当前工作目录」(current working directory)。这两个相当于以前的 os.path.expanduser('~') 和 os.getcwd(),不过显然新写法看着更清爽,是不是?

教学 03 / 23· 已读

二、用 / 来拼接路径

路径拼接是最常见的操作,没有之一。看看老写法:

Python· 可在网页运行
import os

base = '/tmp'
data_path = os.path.join(base, 'demo', 'sub', 'foo.txt')
print(data_path)

输出:

文本
/tmp/demo/sub/foo.txt

这个 os.path.join 用是好用,但写起来嘴里得念好几遍 os path join,手指都不想动了。

然后看看 pathlib 是怎么玩的:

Python· 可在网页运行
from pathlib import Path

base = Path('/tmp')
data_path = base / 'demo' / 'sub' / 'foo.txt'
print(data_path)

输出:

文本
/tmp/demo/sub/foo.txt

注意看:拼接路径用的是 / 这个操作符。是不是有点神奇?

为什么啊?因为 Path 重载了 __truediv__(也就是除法操作符),所以 Path('/tmp') / 'demo' 这种写法就被翻译成了路径拼接。这种设计简直是天才,因为路径在 URL、Linux 文件系统里用的本来就是 /,跟我们脑子里的语义完全一致。

来个对比表,看看是不是清爽多了:

老写法新写法
os.path.join(a, b, c)Path(a) / b / c
os.path.join(os.path.dirname(__file__), 'data')Path(__file__).parent / 'data'
os.path.expanduser('~/Documents')Path.home() / 'Documents'

而且 / 还可以拿一个 Path 跟字符串混着用,结果都是 Path 对象:

Python· 可在网页运行
from pathlib import Path

p1 = Path('/tmp') / 'foo'
p2 = Path('/tmp') / Path('foo')
p3 = 'foo' / Path('tmp')

print(p1)
print(p2)
print(p3)

输出:

文本
/tmp/foo
/tmp/foo
foo/tmp

不管 / 左边还是右边是字符串,只要有一边是 Path,结果就还是 Path。

教学 04 / 23· 已读

三、常用属性,一锅端

各位写过爬虫或者文件处理代码的话,对「拿到一个路径,我要它的文件名」、「我要它的扩展名」这种需求肯定不陌生。老写法散布在 os.path.basename、os.path.splitext 这些函数里,记起来挺麻烦。

Path 把这些都做成属性了,一个个看。

教学 05 / 23· 已读

3.1 .name:完整文件名(带后缀)

Python· 可在网页运行
from pathlib import Path

p = Path('/tmp/demo/foo.txt')
print(p.name)

输出:

文本
foo.txt

相当于以前的 os.path.basename(...)。

教学 06 / 23· 已读

3.2 .stem:去掉后缀的「主干」

Python· 可在网页运行
from pathlib import Path

p = Path('/tmp/demo/foo.txt')
print(p.stem)

输出:

文本
foo

这个就是文件名去掉扩展名的部分,特别适合用来生成「同名但换后缀」的新文件,比如 foo.txt 转 foo.json。

教学 07 / 23

3.3 .suffix:扩展名(带点)

Python· 可在网页运行
from pathlib import Path

p = Path('/tmp/demo/foo.txt')
print(p.suffix)

输出:

文本
.txt

注意是带点的。如果你需要不带点的,自己 [1:] 切一下就好。

那么如果是 foo.tar.gz 这种多后缀的呢?

Python· 可在网页运行
from pathlib import Path

p = Path('archive.tar.gz')
print(p.suffix)
print(p.suffixes)

输出:

文本
.gz
.tar.gz

看到了吗?.suffix 只给最后一个,.suffixes 给一个列表。

练习 1 / 4·提取路径的 name / suffix / stem题目有问题?

请:

  1. 从 pathlib 导入 Path
  2. 创建路径对象 p = Path('/tmp/data/foo.txt')
  3. 依次 print 它的 .name、.suffix、.stem

输出应该是:

文本
foo.txt
.txt
foo

注意:print(p.name) 输出的是 foo.txt,不是 'foo.txt'——直接打印不带引号。

main.py
可编辑
🔒做对当前题解锁下一段 ·0/4

推荐一个,全网最全最友好的中文 AI 编程指南: coding.stormzhang.ai

← 上一章17 · 代码可读性
pathlib:现代化路径处理
下一章 →19 · 异常处理
本章目录

pathlib:现代化路径处理

  1. 教学 01pathlib 路径处理
  2. 教学 02一、第一个 Path
  3. 教学 03二、用 `/` 来拼接路径
  4. 教学 04三、常用属性,一锅端
  5. 教学 053.1 `.name`:完整文件名(带后缀)
  6. 教学 063.2 `.stem`:去掉后缀的「主干」
  7. 教学 073.3 `.suffix`:扩展名(带点)
  8. 练习 1提取路径的 name / suffix / stem
  9. 练习 2 🔒用 / 操作符拼接路径
  10. 教学 08 🔒3.4 `.parent`:父目录
  11. 教学 09 🔒3.5 `.parents`:所有祖先目录
  12. 练习 3 🔒拿父目录和祖先目录
  13. 练习 4 🔒多后缀文件:.suffixes
  14. 教学 10 🔒3.6 `.anchor`:锚点
  15. 教学 11 🔒3.7 综合演示
  16. 教学 12 🔒四、判断和信息
  17. 教学 13 🔒五、遍历目录
  18. 教学 14 🔒六、读写文件
  19. 教学 15 🔒七、创建和删除
  20. 教学 16 🔒八、路径转换
  21. 教学 17 🔒九、改个名字:`with_name` / `with_stem` / `with_suffix`
  22. 教学 18 🔒十、跨平台:`PurePath` 系列
  23. 教学 19 🔒十一、老写法对照表 + 常见踩坑
  24. 教学 20 🔒十二、小实战:递归统计某目录下所有 `.py` 文件的总行数
  25. 教学 21 🔒十三、彩蛋:和老 API 互通
  26. 教学 22 🔒十四、小结
  27. 教学 23 🔒文件写到哪里了

学习目录