小白学 Python
课程GitHub
© 2026 小白学 Python · 基于 walter201230/Python 教程
课程目录GitHub
Python 环境加载中…
pathlib:现代化路径处理0 / 4
1234

pathlib:现代化路径处理

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

教学 01 / 05· 已读

第十八节: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
  • 判断要 os.path.exists 加 os.path.isfile
  • 方法散落在 os、os.path 两个模块

更要命的是——路径在这里只是个普通字符串。字符串不知道自己代表的是文件还是目录,所有操作都得拿着字符串去喂给一堆函数。

有没有一种写法,让路径自己「活」起来?

让 Path('data/foo.txt') 这个对象本身就知道:

  • 自己叫什么名字(p.name)
  • 自己的后缀是什么(p.suffix)
  • 自己的父目录是哪儿(p.parent)
  • 自己存不存在(p.exists())
  • 自己里面装着什么内容(p.read_text())

有的——这就是 Python 标准库 pathlib。

老 vs 新对照

操作老写法(os.path)新写法(pathlib)
拼接路径os.path.join(a, b, c)Path(a) / b / c
文件名os.path.basename(p)Path(p).name
扩展名os.path.splitext(p)[1]Path(p).suffix
父目录os.path.dirname(p)Path(p).parent
是否存在os.path.exists(p)Path(p).exists()

记住一句话:写新代码就用 pathlib,别再 os.path.join 一条道走到黑了。

本章我们专注于「路径解析、属性提取、拼接」这些纯路径操作——它们在浏览器环境里也能正常运行。read_text / write_text / mkdir 这类真访问文件系统的方法,我们留给本地环境去玩。

教学 02 / 05· 已读

一、第一个 Path

pathlib 的核心是一个类:Path。所有操作都从它开始。

1、从字符串创建 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('...'),怎么类型变成了 PosixPath?

这是因为 Path 是个聪明家伙,会根据当前操作系统自动选择子类:

  • macOS / Linux → PosixPath
  • Windows → WindowsPath

平时根本不用关心这个区别——直接 Path('...') 就完事了。

2、绝对路径

绝对路径(以 / 开头)也照样行:

python
from pathlib import Path

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

输出:

/tmp/data/foo.txt

3、两个常用「快捷入口」

python
from pathlib import Path

print(Path.home())   # 当前用户的家目录
print(Path.cwd())    # 当前工作目录

可能的输出:

/Users/walter
/Users/walter/projects/demo

对比老写法:

老 API新 API
os.path.expanduser('~')Path.home()
os.getcwd()Path.cwd()

在 Pyodide / 浏览器环境里,Path.home() 和 Path.cwd() 也能跑——只是结果是虚拟的。

教学 03 / 05

二、常用属性,一锅端

拿到一个路径,最常见的需求是「取出某一部分」——文件名、扩展名、父目录……

老写法散布在 os.path.basename、os.path.splitext、os.path.dirname 一堆函数里。Path 把这些都做成了属性。

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

python
from pathlib import Path

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

输出:

foo.txt

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

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

python
from pathlib import Path

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

输出:

foo

特别适合用来生成「同名换格式」的新文件——比如 foo.txt 转 foo.json。

3、.suffix:扩展名(带点)

python
from pathlib import Path

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

输出:

.txt

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

4、.suffixes:所有扩展名(用于多后缀文件)

foo.tar.gz 这种「多后缀」的怎么办?

python
from pathlib import Path

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

输出:

.gz
['.tar', '.gz']
  • .suffix 只给最后一个后缀
  • .suffixes 给一个列表,包含所有后缀

5、.parent:父目录

python
from pathlib import Path

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

输出:

/tmp/demo/sub

相当于 os.path.dirname(...),但读起来自然多了。

6、.parents:所有祖先目录

python
from pathlib import Path

p = Path('/tmp/demo/sub/foo.txt')
print(p.parents[0])    # 一级父目录
print(p.parents[1])    # 二级祖先
print(p.parents[2])    # 三级祖先

输出:

/tmp/demo/sub
/tmp/demo
/tmp

.parents 是一个序列,可以用下标访问,也可以 for 循环遍历。

7、综合演示

python
from pathlib import Path

p = Path('/Users/walter/projects/demo/main.py')

print('name   :', p.name)
print('stem   :', p.stem)
print('suffix :', p.suffix)
print('parent :', p.parent)
print('parts  :', p.parts)

输出:

name   : main.py
stem   : main
suffix : .py
parent : /Users/walter/projects/demo
parts  : ('/', 'Users', 'walter', 'projects', 'demo', 'main.py')

最后一个 .parts 把整个路径切成元组,逐段处理特别方便。

是不是发现路径在 pathlib 里彻底不是字符串了——它是一个有属性、有方法的「对象」?

练习 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
本章目录

pathlib:现代化路径处理

  1. 教学 01第十八节:pathlib——现代化路径处理
  2. 教学 02一、第一个 Path
  3. 教学 03二、常用属性,一锅端
  4. 练习 1提取路径的 name / suffix / stem
  5. 教学 04三、用 `/` 拼接路径
  6. 练习 2 🔒用 / 操作符拼接路径
  7. 练习 3 🔒拿父目录和祖先目录
  8. 教学 05四、文件系统操作(简介)
  9. 练习 4 🔒多后缀文件:.suffixes
← 上一章17 · 代码可读性
pathlib:现代化路径处理
下一章 →19 · 异常处理