【Pathlib】一文弄懂Python中的路径问题

文摘   科技   2024-07-15 08:10   江苏  








01


引言





大家好,我是AI算法之道!


Python是我最喜欢的编程语言之一,它向来以其简单性、多功能性和可读性而闻名。



然而,构建Python应用程序时,我经常会遇到一些路径上的问题,过去我曾经尝试过将路径拼接为字符串或者通过使用os和grob来拼凑路径。


好消息是,自从Python 3.4开始,Python中有了一个新模块:pathlib。一个模块就能完成所有路径相关的工作,并能在任何操作系统上无缝运行。可以毫不夸张的说,pathlib解决了我所有的痛点。


在本文中,我们将深入探讨Python中的路径问题,希望可以帮助到大家!





02


 导入

pathlib 模块是标准 Python库的一部分,因此无需额外安装。

from pathlib import Path



03


 文件夹结构


我创建了以下这个混乱的文件夹结构,作为本教程中的一个示例,

如上所示,该文件夹结构主要包括:

  • 包含一些文件的主文件夹 data_4 

  • 一个子文件夹 (more_data) 包含更多文件
  • 一个不包含任何文件的子文件夹(temp)



04


 path object


使用 pathlib 创建的所有路径都可以被存储为路径对象。这一点非常好,因为无论在 Windows、Linux 还是 Mac 上使用,以路径对象表示的路径都能正确显示。
路径对象在不同系统上表示的含义不同,如下:
  • Windows 上的 WindowsPosix
  • Linux 和 Mac 上的 Posix

路径对象中有很多函数,可以方便地构建和检查路径。现在,让我们看一些实际例子中的效果。



05


获取路径

有时我们需要获取当前目录,则使用以下命令:

print(Path.cwd())
# OutputPosixPath('/home/pawjast/Documents/my github/medium/code')
如果我们需要显示home目录,则使用以下命令:
print(Path.home())
# OutputPosixPath('/home/pawjast')


06


字符串转化为路径


有时我们需要将字符串转化为路径,则推荐以下两种方法:

  • 尽量使用正斜线

my_path = Path.cwd() / "datasets" / "data_4"

注意:第一项必须是路径对象,斜线方法才会起作用。

  • 使用 joinpath() 方法

my_path = Path.cwd().joinpath("datasets", "data_4")

两种情况下的输出结果,如下:

PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4')


07


列出当前目录下的所有文件和文件夹

如果我们需要列出当前目录下的所有文件,在Pathlib中也有两种方法,分别如下:

  • 使用 .iterdir() 函数

[path for path in my_path.iterdir()]
  • 使用 .glob() 函数

list(my_path.glob("*"))

两种情况下的输出结果如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/hi.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data1.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data2.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/abc.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/cde.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp')]




08


检查子目录

如果我们需要查看当前目录和其子目录下的文件,我们需要使用 .rglob() 方法(r 代表递归)。

list(my_path.rglob("*"))

这将同步展示子目录下的内容,如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/hi.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data1.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data2.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/abc.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/cde.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/abc.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/whatshere.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/hello.html'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/yyy.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/data3.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/xxx.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/abcd.py'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/surprise.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp/dead_end')]




09


获取相对路径

如果要获取相对路径,我们需要定义路径的相对位置。

[path.relative_to(my_path) for path in my_path.rglob("*")]

这将输出如下:

[PosixPath('more_data'), PosixPath('hi.md'), PosixPath('data1.csv'), PosixPath('data2.csv'), PosixPath('abc.txt'), PosixPath('cde.txt'), PosixPath('temp'), PosixPath('more_data/abc.csv'), PosixPath('more_data/go_deeper'), PosixPath('more_data/whatshere.md'), PosixPath('more_data/hello.html'), PosixPath('more_data/yyy.txt'), PosixPath('more_data/data3.csv'), PosixPath('more_data/xxx.txt'), PosixPath('more_data/go_deeper/abcd.py'), PosixPath('more_data/go_deeper/surprise.csv'), PosixPath('temp/dead_end')]




10


仅获取文件

目前为止我们已经看到了几种生成文件、文件夹和子文件夹完整列表的方法。

让我们说得更具体一些。如果我们只想要文件的路径,就需要使用函数 .is_file() 来操作,代码如下:

# In the current folder - way 1[path for path in my_path.iterdir() if path.is_file()]

或者,换种写法:

# In the current folder - way 2[path for path in my_path.glob("*") if path.is_file()]

上述代码结果如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/hi.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data1.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data2.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/abc.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/cde.txt')]

这种方法也适用于子目录情形,代码如下:

[path for path in my_path.rglob("*") if path.is_file()]

结果如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/hi.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data1.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data2.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/abc.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/cde.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/abc.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/whatshere.md'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/hello.html'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/yyy.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/data3.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/xxx.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/abcd.py'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/surprise.csv')]



11


仅获取文件夹

同样,大家也可以只列出所有的文件夹和子文件夹

[path for path in my_path.rglob("*") if path.is_dir()]

输出如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp/dead_end')]

注意:在这种情况下,顺序有点不对。请记住,我们将所有路径存储在一个列表中,排序可以解决这个问题。

sorted([path for path in my_path.rglob("*") if path.is_dir()])

输出如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/temp/dead_end')]




12


获取特定类型的文件

我们知道可以通过glob()函数获取特定类型的文件,这同样适用于pathlib中的 .glob() 和 .rglob()。

# Show `.csv` onlylist(my_path.rglob("*.csv"))

输出如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data1.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/data2.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/abc.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/data3.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/surprise.csv')]




13


使用模式匹配


比方说,我们想要查找名称中包含 "abc "的所有文件。

list(my_path.rglob("*abc*"))

则输出如下:

[PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/abc.txt'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/abc.csv'), PosixPath('/home/pawjast/Documents/my github/medium/code/datasets/data_4/more_data/go_deeper/abcd.py')]






14


总结


本文介绍了python中的pathlib库来操作路径的几个函数技巧,希望这些小技巧可以帮助到大家,提升大家的工作效率!



您学废了吗?






点击上方小卡片关注我




添加个人微信,进专属粉丝群!


AI算法之道
一个专注于深度学习、计算机视觉和自动驾驶感知算法的公众号,涵盖视觉CV、神经网络、模式识别等方面,包括相应的硬件和软件配置,以及开源项目等。
 最新文章