如何使用pathlib模块在Python3中操作文件系统路径
作者选择了 COVID-19 Relief Fund 作为 Write for DOnations 计划的一部分来接受捐赠。
介绍
Python 3 包括 pathlib 模块 用于不可知地操作文件系统路径,无论操作系统如何。 pathlib
类似于 os.path 模块,但 pathlib
提供了比 os.path
更高级别且通常更方便的接口。
我们可以通过分层路径识别计算机上的文件。 例如,我们可能会使用以下路径识别计算机上的文件 wave.txt
:/Users/sammy/ocean/wave.txt
。 操作系统表示路径略有不同。 Windows 可能表示 wave.txt
文件的路径,如 C:\Users\sammy\ocean\wave.txt
。
如果在您的 Python 程序中,您可能会发现 pathlib
模块很有用:在文件系统上创建或移动文件,在文件系统上列出所有匹配给定扩展名或模式的文件,或基于操作系统创建适当的文件路径关于原始字符串的集合。 虽然您可能能够使用其他工具(如 os.path
模块)来完成其中许多任务,但 pathlib
模块允许您以高度可读性和最少的数量执行这些操作的代码。
在本教程中,我们将介绍一些使用 pathlib
模块来表示和操作文件系统路径的方法。
先决条件
为了充分利用本教程,建议您熟悉 Python 3 中的编程。 您可以查看这些教程以获取必要的背景信息:
构造 Path
实例
pathlib
模块提供了几个 类,但最重要的一个是 Path
类。 Path
类的实例代表我们计算机文件系统上文件或目录的路径。
例如,以下代码实例化了一个 Path
实例,该实例表示 wave.txt
文件的部分路径:
from pathlib import Path wave = Path("ocean", "wave.txt") print(wave)
如果我们运行此代码,我们将收到如下输出:
Outputocean/wave.txt
from pathlib import Path
使 Path
类可用于我们的程序。 然后 Path("ocean", "wave.txt")
实例化一个新的 Path
实例。 打印输出显示 Python 在我们给它的两个路径组件之间添加了 /
的适当操作系统分隔符:"ocean"
和 "wave.txt"
。
注意: 根据您的操作系统,您的输出可能与本教程中显示的示例输出略有不同。 例如,如果您运行的是 Windows,则第一个示例的输出可能类似于 ocean\wave.txt
。
目前,分配给wave
变量的Path
对象包含一个相对路径。 换句话说,ocean/wave.txt
可能存在于我们文件系统的多个位置。 例如,它可能存在于 /Users/user_1/ocean/wave.txt
或 /Users/user_2/research/ocean/wave.txt
中,但我们没有具体说明我们指的是哪一个。 相比之下, 绝对路径 明确地指代文件系统上的一个位置。
您可以使用 Path.home()
获取当前用户主目录的绝对路径:
home = Path.home() wave_absolute = Path(home, "ocean", "wave.txt") print(home) print(wave_absolute)
如果我们运行此代码,我们将收到大致如下所示的输出:
Output/Users/sammy /Users/sammy/ocean/wave.txt
注意: 如前所述,您的输出将根据您的操作系统而有所不同。 当然,您的主目录也将不同于 /Users/sammy
。
Path.home()
返回一个 Path
实例,其中包含指向当前用户主目录的绝对路径。 然后我们将这个 Path
实例和字符串 "ocean"
和 "wave.txt"
传递到另一个 Path
构造函数中,以创建到 wave.txt
的绝对路径文件。 输出显示第一行是主目录,第二行是主目录加上 ocean/wave.txt
。
此示例还说明了 Path
类的一个重要特性:Path
构造函数接受字符串和预先存在的 Path
对象。
让我们更仔细地看一下 Path
构造函数中对字符串和 Path
对象的支持:
shark = Path(Path.home(), "ocean", "animals", Path("fish", "shark.txt")) print(shark)
如果我们运行此 Python 代码,我们将收到类似于以下内容的输出:
Output/Users/sammy/ocean/animals/fish/shark.txt
shark
是我们使用 Path
对象(Path.home()
和 Path("fish", "shark.txt")
)和字符串("ocean"
和 "animals"
)。 Path
构造函数智能地处理这两种类型的对象,并使用适当的操作系统分隔符将它们干净地连接起来,在本例中为 /
。
访问文件属性
现在我们已经学习了如何构建 Path
实例,让我们回顾一下如何使用这些实例来访问有关文件的信息。
我们可以使用 name
和 suffix
属性来访问文件名和文件后缀:
wave = Path("ocean", "wave.txt") print(wave) print(wave.name) print(wave.suffix)
运行此代码,我们将收到类似于以下内容的输出:
Output/Users/sammy/ocean/wave.txt wave.txt .txt
此输出显示我们路径末尾的文件名是 wave.txt
,该文件的后缀是 .txt
。
Path
实例还提供 with_name
函数,允许您无缝创建具有不同名称的新 Path
对象:
wave = Path("ocean", "wave.txt") tides = wave.with_name("tides.txt") print(wave) print(tides)
如果我们运行它,我们将收到如下输出:
ocean/wave.txt ocean/tides.txt
代码首先构造一个 Path
实例,该实例指向一个名为 wave.txt
的文件。 然后,我们在 wave
上调用 with_name
方法以返回第二个 Path
实例,该实例指向一个名为 tides.txt
的新文件。 路径的 ocean/
目录部分保持不变,最终路径为 ocean/tides.txt
访问祖先
有时访问包含给定路径的目录很有用。 让我们考虑一个例子:
shark = Path("ocean", "animals", "fish", "shark.txt") print(shark) print(shark.parent)
如果我们运行此代码,我们将收到如下所示的输出:
Outputocean/animals/fish/shark.txt ocean/animals/fish
Path
实例上的 parent
属性返回给定文件路径的最直接祖先。 在这种情况下,它返回包含 shark.txt
文件的目录:ocean/animals/fish
。
我们可以连续多次访问 parent
属性以向上遍历给定文件的祖先树:
shark = Path("ocean", "animals", "fish", "shark.txt") print(shark) print(shark.parent.parent)
如果我们运行此代码,我们将收到以下输出:
Outputocean/animals/fish/shark.txt ocean/animals
输出与之前的输出类似,但现在我们通过第二次访问 .parent
遍历了更高的级别。 shark.txt
上两个目录是 ocean/animals
目录。
使用 Glob 列出文件
也可以使用 Path
类使用 glob
方法列出文件。
假设我们有一个如下所示的目录结构:
└── ocean ├── animals │ └── fish │ └── shark.txt ├── tides.txt └── wave.txt
ocean
目录包含文件 tides.txt
和 wave.txt
。 我们有一个名为 shark.txt
的文件嵌套在 ocean
目录下,一个 animals
目录和一个 fish
目录:ocean/animals/fish
。
要列出 ocean
目录中的所有 .txt
文件,我们可以说:
for txt_path in Path("ocean").glob("*.txt"): print(txt_path)
此代码将产生如下输出:
Outputocean/wave.txt ocean/tides.txt
"*.txt"
glob 模式 查找所有以 .txt
结尾的文件。 由于代码示例在 ocean
目录中执行该 glob,因此它返回 ocean
目录中的两个 .txt
文件:wave.txt
和 [X150X ]。
注意: 如果您想复制此示例中显示的输出,您需要在您的计算机上模仿此处所示的目录结构。
我们也可以递归地使用 glob
方法。 要列出 ocean
目录及其所有子目录中的所有 .txt
文件,我们可以说:
for txt_path in Path("ocean").glob("**/*.txt"): print(txt_path)
如果我们运行此代码,我们将收到如下输出:
Outputocean/wave.txt ocean/tides.txt ocean/animals/fish/shark.txt
glob 模式的 **
部分将递归匹配此目录及其下的所有目录。 因此,我们不仅在输出中有 wave.txt
和 tides.txt
文件,而且我们还收到了嵌套在 ocean/animals/fish
下的 shark.txt
文件。
计算相对路径
我们可以使用 Path.relative_to
方法来计算相对于彼此的路径。 例如,当您想要检索长文件路径的一部分时,relative_to
方法很有用。
考虑以下代码:
shark = Path("ocean", "animals", "fish", "shark.txt") below_ocean = shark.relative_to(Path("ocean")) below_animals = shark.relative_to(Path("ocean", "animals")) print(shark) print(below_ocean) print(below_animals)
如果我们运行它,我们将收到如下输出:
Outputocean/animals/fish/shark.txt animals/fish/shark.txt fish/shark.txt
relative_to
方法返回一个相对于给定参数的新 Path
对象。 在我们的示例中,我们计算 Path
到 shark.txt
相对于 ocean
目录,然后相对于 ocean
和 animals
目录。
如果 relative_to
因为我们给它一个不相关的路径而无法计算答案,它会引发 ValueError
:
shark = Path("ocean", "animals", "fish", "shark.txt") shark.relative_to(Path("unrelated", "path"))
我们将收到从该代码引发的 ValueError
异常,如下所示:
OutputTraceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/Python3.8/pathlib.py", line 899, in relative_to raise ValueError("{!r} does not start with {!r}" ValueError: 'ocean/animals/fish/shark.txt' does not start with 'unrelated/path'
unrelated/path
不是 ocean/animals/fish/shark.txt
的一部分,因此 Python 无法为我们计算相对路径。
结论
pathlib
模块是 Python 标准库 的强大部分,它可以让我们在任何操作系统上快速操作文件系统路径。 在本教程中,我们学习了使用 pathlib
的一些关键实用程序来访问文件属性、使用 glob 模式列出文件以及遍历父文件和目录。
pathlib
模块公开了我们在本教程中没有介绍的其他类和实用程序。 现在您有了基线,您可以使用 pathlib 模块的文档 了解更多关于其他可用类和实用程序的信息。
如果您对使用其他 Python 库感兴趣,请查看以下教程: