如何使用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 实例,让我们回顾一下如何使用这些实例来访问有关文件的信息。

我们可以使用 namesuffix 属性来访问文件名和文件后缀:

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.txtwave.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.txttides.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 对象。 在我们的示例中,我们计算 Pathshark.txt 相对于 ocean 目录,然后相对于 oceananimals目录。

如果 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 库感兴趣,请查看以下教程: