pathlib
模块是在
Python3.4
版本中首次被引入到标准库中的,作为一个可选模块。

Python3.6
开始,内置的
open
函数以及
os

shutil

os.path
模块中的各种函数都可以正确地使用
pathlib.Path
对象了。

最初,
pathlib
给人的感觉只是
os.path
的一个不必要的面向对象版本,
不过,当你实际去了解
pathlib
之后,会发现
pathlib
实际上绝不是一个简单的面向对象版本,
而是实实在在的解决了
os.path
存在的一些问题。

1. os.path VS pathlib

1.1. 路径规范化

对于
os.path
来说,路径的分隔用
正斜杆

\
)还是
反斜杠

/
)需要自己根据操作系统来确定。
或者,每一个路径拼接的地方,都用
os.path.join
来连接。
而使用
pathlib
的话,直接用
反斜杠

/
)即可,不用担心操作系统的不同。

比如:

import os

# windows系统中测试

os.path.join("a/b", "c.txt")
# 运行结果 错误
# 'a/b\\c.txt'

os.path.join("a", "b", "c.txt")
# 运行结果 正确
# 'a\\b\\c.txt'

从代码可以看出,每一层文件夹都必须用
join
连接才能正确适应不同系统。
而在
pathlib
中,则不需要考虑这么多。

from pathlib import Path

Path("a/b").joinpath("c.txt")
# WindowsPath('a/b/c.txt')

Path("a").joinpath("b").joinpath("c.txt")
# WindowsPath('a/b/c.txt')

使用
pathlib
,在
windows
或者
linux
中,统一使用
反斜杠

/
)来分隔文件夹。

路径规范化之后的好处就是代码更加简洁。
比如:下面这个重命名文件的例子(
a/b/c/d.csv => a/b/c.csv

# os.path 方式
os.rename(os.path.join("a", "b", "c", "d.csv"), os.path.join("a", "b", "c.csv"))

# pathlib 方式
Path("a/b/c/d.csv").reanme("a/b/c.csv")

哪种方式更清晰简洁不言而喻。

1.2. 字符串和对象

为什么要用对象来表示路径?

先看下面3个字符串变量:

student = '{"name": "databook", "score": "90"}'
graduate_date = "2023-07-01"
home_directory = '/home/databook'

这3个字符串其实代表不同的事物:一种是 JSON blob,一种是日期,一种是文件路径。

再看下面3个用对象表示的变量:

from datetime import date
from pathlib import Path

student = {"name": "databook", "score": "90"}
graduate_date = date(2023, 7, 1)
home_directory = Path('/home/databook')

用字符串来表示变量确实简洁,但也导致每个变量失去了其本身的意义,
程序无法区分这个变量代表的是JSON,还是日期,还是一个路径,从而增加了程序的不确定性。
程序规模大了,或者复杂性提高了之后,存在很大的隐患。

os.path

pathlib
就是这样的关系,
os.path
使用字符串表示路径,
pathlib
使用
Path
对象表示路径。

1.3. 读写文件

pathlib
的路径对象(
Path
)可以直接读写文件,因此也能大大简化读写文件的代码。

不用
pathlib
的读写文件方式:

import os

# 读取文件
fp = os.path.join("a", "b.txt")
with open(fp, "r") as f:
    f.read()

# 写入文件
with open(fp, "w") as f:
    f.write("hello")

使用
pathlib
的话:

from pathlib import Path

# 读取文件
Path("a/b.txt").read_text()

# 写入文件
Path("a/b.txt").write_text("hello)

2. pathlib的性能

pathlib
用面向对象的方式处理路径,难免让人觉得会比传统的方式慢很多,也就是存在性能问题。
那么,
pathlib
到底会比传统方式慢多少?通过下面的简单示例来看看。

传统方式:

def a(d="D:/miniconda3/Lib/site-packages"):
    from os import getcwd, walk

    extension = ".py"
    count = 0
    for root, directories, filenames in walk(d):
        for filename in filenames:
            if filename.endswith(extension):
                count += 1
                
    print(f"{count} Python files found")

if __name__ == "__main__":
    import time

    t0 = time.time()
    a()
    t1 = time.time()
    print(t1 - t0)

# 运行结果:
7875 Python files found
0.31201744079589844

pathlib
方式:

def b(d="D:/miniconda3/Lib/site-packages"):
    from pathlib import Path

    extension = ".py"
    count = 0
    for filename in Path(d).rglob(f"*{extension}"):
        count += 1

    print(f"{count} Python files found")

if __name__ == "__main__":
    import time

    t0 = time.time()
    b()
    t1 = time.time()
    print(t1 - t0)

# 运行结果:
7875 Python files found
0.44898128509521484

读取的标准库中的文件,总共将近
8000
个文件,运行多次后,时间大概相差
0.1秒
左右。
pathlib
的性能确实略逊于传统方式,但是将近
8000
个文件,也只慢了
0.1秒

如果不是大规模处理文件的话,还是用
pathlib
更好。

3. 总结

总的来说,与传统的
os.path
模块相比,
pathlib
提供了一种更现代和面向对象的方式来处理文件路径。
它支持跨平台的文件路径操作,使得开发者可以更容易地编写可移植的代码。
此外,
pathlib
还提供了链式调用的能力,使得代码更加简洁和易读。

因此,为了代码更加简洁、易读和可维护,推荐使用
pathlib
来替代传统的
os.path

标签: none

添加新评论