你应该使用pathlib替代os.path

在Python 3.4之前和路径相关操作函数都放在os模块里面,尤其是 os.path 这个子模块,可以说 os.path 模块非常常用。而在Python 3.4,标准库添加了新的模块 - pathlib,它使用面向对象的编程方式来表示文件系统路径。

作为一个从Python 2时代过来的人,已经非常习惯使用os,那么为什么我说「应该使用pathlib替代os.path」呢?基于这段时间的体验,我列出了几个pathlib模块的优势和特点。

基本用法

在过去,文件的路径是纯字符串,现在它会是一个 pathlib.Path 对象:

使用str函数可以把一个Path对象转化成字符串。在Python 3.6之前,Path对象是不能作为os模块下的参数的,需要手动转化成字符串:

从Python 3.6开始,这些接受路径作为参数的函数内部会先通过 os.fspath 调用Path对象的 __fspath__ 方法获得字符串类型的路径再去执行下面的逻辑。所以要注意: 如果你想全面使用pathlib模块,应该使用Python3.6或者更高版本!

和os功能对应的方法列表

先看一下os(os.path)模块里部分函数与 pathlib.Path 对应的方法吧。下面列出的这些可以直接用pathlib里面的用法代替:

os and os.path pathlib
os.path.abspath Path.resolve
os.chmod Path.chmod
os.mkdir Path.mkdir
os.rename Path.rename
os.replace Path.replace
os.rmdir Path.rmdir
os.removeos.unlink Path.unlink
os.getcwd Path.cwd
os.path.exists Path.exists
os.path.expanduser Path.expanduser and  Path.home
os.path.isdir Path.is_dir
os.path.isfile Path.is_file
os.path.islink Path.is_symlink
os.stat Path.statPath.ownerPath.group
os.path.isabs PurePath.is_absolute
os.path.join PurePath.joinpath
os.path.basename PurePath.name
os.path.dirname PurePath.parent
os.path.samefile Path.samefile
os.path.splitext PurePath.suffix

举2个例子:

接着感受下pathlib带来的变化。

/ 拼接路径

过去路径拼接最正确的方法是用 os.path.join :

现在可以用 pathlib.Path 提供的joinpath来拼接:

但是更简单和方便的方法是用 / 运算符:

这也不是什么神奇魔法,有兴趣的可以看Path对象 __truediv____rtruediv__ 方法的实现。

链式调用

链式调用是OOP带来的重要改变,从前面的例子中也能感受到,过去的都是把路径作为函数参数传进去,现在可以链式调用。我们看一个更复杂一点的例子:

长不长?现在的写法呢:

是不是非常符合我们从左向右的阅读习惯呢?

自带属性

Path对象带了多个有用的属性

parent/parents

如果想获得某个文件的父级目录通常需要使用 os.path.dirname 或者字符串的rpartition(或split)方法:

如果想获得父级的父级更麻烦一些,例如用 os.path.dirname ,需要这样:

使用Path对象的parents属性可以拿到各级目录列表(索引值越大越接近root),而parent就表示父级目录:

由于parent返回的还是Path对象,所以可以链式的获取其parent属性。

suffix/stem

在过去获得文件后缀名,以及去掉后缀的文件名字,需要使用 os.path.basenameos.path.splitext :

现在就很方便了:

注意: 当文件有多个后缀,可以用 suffixes 返回文件所有后缀列表:

实用方法

Path对象里面有多个实用的方法,我举例一些。

touch方法

Python语言没有内置创建文件的方法(linux下的touch命令),过去这么做:

现在可以直接用Path的touch方法:

touch接受 mode 参数,能够在创建时确认文件权限,还能通过 exist_ok 参数方式确认是否可以重复touch(默认可以重复创建,会更新文件的mtime)

home

获得用户的HOME目录比较常见,过去的写法:

现在就 Path.home 就可以了:

读写文件

Path对象自带了操作文件的方法:

可以用 write_text 写入字符串,用 write_bytes 将文件以二进制模式打开写入字节数据。对应的,可以用 read_text 读取文本内容,也可以用 read_bytes 以字节对象的形式返回路径指向的文件的二进制内容。还可以用 open 获得文件句柄。

不过需要注意,Path里面带的这几个方法只是一些「快捷方式」,「一次性的」。举个例子:

可以看到,多次写入最终结果是最后一次写入的内容。而读取也没有缓存区,全部读取出来。其实读一下源码即能理解:

**在实际工作中这些方法要谨慎使用!``

with name/with suffix

以前我写过一些修改文件名字或者路径后缀的需求:基于某个文件路径生成另外一个文件路径。举个例子,有一个文件地址 '/home/gentoo/screenshot/abc.jpg' ,2个需求:

  1. 获得转成png格式的路径

  2. 把图片名字改成  123

过去需要这么做:

可读性很差。现在呢:

mkdir

过去创建目录时,用 os.mkdir 只能创建一级目录:

所以通常这种一次要创建多级目录,需要用到 os.makedirs ,我一直觉得这么搞很分裂。在Path对应上有mkdir方法,还接受 parents ,以及 modeexist_ok 参数:

我认为这么用的体验着实好了很多~

owner

有时候操作文件前需要确认拥有此文件的用户,过去我都是这么写:

现在封装起来可以直接用了:

后记

以上就是我使用的体验了, pathlib 可以说是Python 3.6+的正确之选~

延伸阅读

  1. https://www.python.org/dev/peps/pep-0428/

  2. https://docs.python.org/3/library/pathlib.html

  3. https://treyhunner.com/2018/12/why-you-should-be-using-pathlib/

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章