如何使用 pathlib 模块在 Python 3 中操纵文件系统路径

作者选择了 COVID-19 救援基金作为 Write for Donations计划的一部分接受捐款。

介绍

Python 3 包括 the pathlib module用于操纵文件系统路径,无论操作系统如何。 pathlib 类似于 os.path 模块,但 pathlib 提供了一个更高的水平 - 而且往往更方便 - 界面比 os.path

例如,我们可以识别计算机上的文件 wave.txt 这个路径: `/Users/sammy/ocean/wave.txt. 操作系统略有不同地表示路径。

您可能会发现pathlib模块有用,如果您在Python程序中:在文件系统上创建或移动文件,在文件系统上列出所有匹配给定的扩展或模式的文件,或基于原始字符串的集合创建操作系统适当的文件路径。

在本教程中,我们将讨论使用pathlib模块来代表和操纵文件系统路径的一些方法。

前提条件

要充分利用本教程,建议您对Python编程有熟悉,您可以查看这些教程以获取必要的背景信息:

如何在Python中编码 3

构建道路实体

pathlib模块提供了几类(https://andsky.com/tech/tutorials/how-to-construct-classes-and-define-objects-in-python-3),但其中最重要的是Path类,而Path类的实例代表了我们计算机文件系统上的文件或目录的路径。

例如,以下代码实例化了一个Path实例,该实例代表了一个wave.txt文件的路径的一部分:

1from pathlib import Path
2
3wave = Path("ocean", "wave.txt")
4print(wave)

如果我们运行此代码,我们将收到如下的输出:

1[secondary_label Output]
2ocean/wave.txt

「從 pathlib 輸入路徑」將「Path」類別提供給我們的程式,然後「Path(「海洋」、「wave.txt」)」會進行一個新的「Path」實例。 打印出來的結果顯示,Python 已在我們給它兩個路徑組件之間添加了適當的操作系統分離器 /:『ocean』和『wave.txt』。

<$>[注] 注: 根据您的操作系统,您的输出可能略有不同于本教程中显示的示例输出。

目前,分配给变量的Path对象包含一个 relative path。 换句话说,在我们的文件系统中可能存在多个位置的ocean/wave.txt。 例如,它可能存在于/Users/user_1/ocean/wave.txt/Users/user_2/research/ocean/wave.txt,但我们尚未准确指定我们所指的位置。

您可以使用Path.home()来获取当前用户的首页目录的绝对路径:

1home = Path.home()
2wave_absolute = Path(home, "ocean", "wave.txt")
3print(home)
4print(wave_absolute)

如果我们运行此代码,我们将收到大约如下的输出:

1[secondary_label Output]
2/Users/sammy
3/Users/sammy/ocean/wave.txt

<$>[注] 注: 如前所述,您的输出将取决于您的操作系统。

「Path.home()」返回一个具有绝对路径的「Path」实例到当前用户的主目录. 然后,我们将此「Path」实例和字符串「ocean」和「wave.txt」转移到另一个「Path」构建器中,以创建到「wave.txt」文件的绝对路径. 输出显示第一行是主目录,第二行是主目录加上「ocean/wave.txt」。

这个例子还说明了Path类的一个重要特征:Path构造器接受既有字符串和现有Path对象。

让我们更仔细地看看Path构建器中的两个字符串和Path对象的支持:

1shark = Path(Path.home(), "ocean", "animals", Path("fish", "shark.txt"))
2print(shark)

如果我们运行这个Python代码,我们将收到类似于以下的输出:

1[secondary_label Output]
2/Users/sammy/ocean/animals/fish/shark.txt

鲨鱼是我们使用Path对象(Path.home()Path(fish,shark.txt)和字符串(海洋动物)构建的文件的Path字符串。

访问文件属性

现在我们已经学会了如何构建Path实例,让我们看看如何使用这些实例访问有关文件的信息。

我们可以使用名称足迹属性来访问文件名和足迹:

1wave = Path("ocean", "wave.txt")
2print(wave)
3print(wave.name)
4print(wave.suffix)

运行此代码,我们将收到类似于以下的输出:

1[secondary_label Output]
2/Users/sammy/ocean/wave.txt
3wave.txt
4.txt

此输出显示,我们路径的末尾的文件名为wave.txt,而该文件的接口为.txt

「Path」实例还提供「with_name」函数,允许您无缝创建具有不同名称的新「Path」对象:

1wave = Path("ocean", "wave.txt")
2tides = wave.with_name("tides.txt")
3print(wave)
4print(tides)

如果我们运行此操作,我们将收到如下的输出:

1ocean/wave.txt
2ocean/tides.txt

代码首先构建了一个Path实例,该实例指向一个名为wave.txt的文件,然后,我们在wave上调用with_name方法,以返回第二个Path实例,该实例指向一个名为tides.txt的新文件。

访问祖先

有时有助于访问包含给定的路径的目录,让我们考虑一个例子:

1shark = Path("ocean", "animals", "fish", "shark.txt")
2print(shark)
3print(shark.parent)

如果我们运行此代码,我们将收到看起来如下的输出:

1[secondary_label Output]
2ocean/animals/fish/shark.txt
3ocean/animals/fish

Path实例上的父母属性返回给定文件路径的最直接的祖先. 在这种情况下,它返回包含shark.txt文件的目录:海洋/动物/鱼

我们可以连续多次访问父母属性,以穿越某个文件的祖先树:

1shark = Path("ocean", "animals", "fish", "shark.txt")
2print(shark)
3print(shark.parent.parent)

如果我们运行此代码,我们将收到以下输出:

1[secondary_label Output]
2ocean/animals/fish/shark.txt
3ocean/animals

输出与以前的输出类似,但现在我们通过第二次访问.parent来跨越了另一个更高的水平。

使用 Glob 列出文件

还可以使用Path类来使用glob方法列出文件。

假设我们有一个目录结构,看起来像这样:

1└── ocean
2    ├── animals
3    │   └── fish
4    │       └── shark.txt
5    ├── tides.txt
6    └── wave.txt

一个海洋目录包含文件tides.txtwave.txt。我们有一个名为shark.txt的文件嵌入海洋目录,一个动物目录和一个目录:海洋/动物/鱼

要列出海洋目录中的所有.txt文件,我们可以说:

1for txt_path in Path("ocean").glob("*.txt"):
2    print(txt_path)

这个代码会产生像这样的输出:

1[secondary_label Output]
2ocean/wave.txt
3ocean/tides.txt

"*.txt" glob pattern找到所有以 .txt 結束的檔案。

<$>[注] 注: 如果您想复制本示例中显示的输出,则需要在您的计算机上模仿此处描述的目录结构。

我们还可以重复使用glob方法,在ocean目录和其所有子目录中列出所有.txt文件,我们可以说:

1for txt_path in Path("ocean").glob("**/*.txt"):
2    print(txt_path)

如果我们运行此代码,我们将收到如下的输出:

1[secondary_label Output]
2ocean/wave.txt
3ocean/tides.txt
4ocean/animals/fish/shark.txt

地球图案的**部分将重复匹配此目录和其下面的所有目录,所以,我们不仅在输出中有wave.txttides.txt文件,而且我们还收到shark.txt文件,该文件被嵌入海洋/动物/鱼

计算机相对路径

我们可以使用 Path.relative_to 方法来计算彼此相对的路径. relative_to 方法在例如,您想要检索长程文件路径的一部分时非常有用。

考虑以下代码:

1shark = Path("ocean", "animals", "fish", "shark.txt")
2below_ocean = shark.relative_to(Path("ocean"))
3below_animals = shark.relative_to(Path("ocean", "animals"))
4print(shark)
5print(below_ocean)
6print(below_animals)

如果我们运行此操作,我们将收到如下的输出:

1[secondary_label Output]
2ocean/animals/fish/shark.txt
3animals/fish/shark.txt
4fish/shark.txt

在我们的示例中,我们计算Pathshark.txt相对于海洋目录,然后相对于海洋动物目录。

如果relative_to无法计算一个答案,因为我们给它一个无关的路径,它会引出一个ValueError:

1shark = Path("ocean", "animals", "fish", "shark.txt")
2shark.relative_to(Path("unrelated", "path"))

我们将收到从这个代码中提取的ValueError例外,这将是这样的:

1[secondary_label Output]
2Traceback (most recent call last):
3  File "<stdin>", line 1, in <module>
4  File "/usr/local/lib/Python3.8/pathlib.py", line 899, in relative_to
5    raise ValueError("{!r} does not start with {!r}"
6ValueError: 'ocean/animals/fish/shark.txt' does not start with 'unrelated/path'

无关 / 路径不是海洋 / 动物 / 鱼 / 鲨鱼.txt的一部分,所以Python 无法为我们计算相对路径。

结论

pathlib模块是Python标准图书馆(https://docs.python.org/3/library/)的强大组成部分,它允许我们在任何操作系统上快速操纵文件系统路径. 在本教程中,我们已经学会了使用一些pathlib的关键实用程序来访问文件属性,列出与全球模式的文件,并穿过家长文件和目录。

pathlib模块揭示了我们在本教程中没有涵盖的其他类和实用程序,现在你有一个基线,你可以使用pathlib模块的文档(https://docs.python.org/3/library/pathlib.html)来了解更多关于其他可用的类和实用程序。

如果您对使用其他 Python 库感兴趣,请查看以下教程:

Published At
Categories with 技术
comments powered by Disqus