告别os.path,拥抱pathlib

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

Python3.6开始,内置的 open 函数以及 osshutilos.path 模块中的各种函数都可以正确地使用 pathlib.Path 对象了。

最初,pathlib给人的感觉只是os.path的一个不必要的面向对象版本,

不过,当你实际去了解pathlib之后,会发现pathlib实际上绝不是一个简单的面向对象版本,

而是实实在在的解决了os.path存在的一些问题。

1. os.path VS pathlib

1.1. 路径规范化

对于os.path来说,路径的分隔用正斜杆\)还是反斜杠/)需要自己根据操作系统来确定。

或者,每一个路径拼接的地方,都用os.path.join来连接。

而使用pathlib的话,直接用反斜杠/)即可,不用担心操作系统的不同。

比如:

python 复制代码
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中,则不需要考虑这么多。

python 复制代码
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

python 复制代码
# 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个字符串变量:

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

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

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

python 复制代码
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.pathpathlib就是这样的关系,os.path使用字符串表示路径,pathlib使用Path对象表示路径。

1.3. 读写文件

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

不用pathlib的读写文件方式:

python 复制代码
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的话:

python 复制代码
from pathlib import Path

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

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

2. pathlib的性能

pathlib用面向对象的方式处理路径,难免让人觉得会比传统的方式慢很多,也就是存在性能问题。

那么,pathlib到底会比传统方式慢多少?通过下面的简单示例来看看。

传统方式:

python 复制代码
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方式:

python 复制代码
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

相关推荐
老胖闲聊24 分钟前
Python Copilot【代码辅助工具】 简介
开发语言·python·copilot
Blossom.11828 分钟前
使用Python和Scikit-Learn实现机器学习模型调优
开发语言·人工智能·python·深度学习·目标检测·机器学习·scikit-learn
曹勖之1 小时前
基于ROS2,撰写python脚本,根据给定的舵-桨动力学模型实现动力学更新
开发语言·python·机器人·ros2
lyaihao2 小时前
使用python实现奔跑的线条效果
python·绘图
ai大师2 小时前
(附代码及图示)Multi-Query 多查询策略详解
python·langchain·中转api·apikey·中转apikey·免费apikey·claude4
小小爬虾3 小时前
关于datetime获取时间的问题
python
蓝婷儿4 小时前
6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础
开发语言·python·学习
chao_7894 小时前
链表题解——两两交换链表中的节点【LeetCode】
数据结构·python·leetcode·链表
大霞上仙5 小时前
nonlocal 与global关键字
开发语言·python
Mark_Aussie6 小时前
Flask-SQLAlchemy使用小结
python·flask