这个库用起来是真的爽!!

来自公众号:Python七号
前段时间,在使用新版本的 Django 时,我发现了 settings.py 的第一行代码从
import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

变成了

from pathlib import PathBASE_DIR = Path(__file__).resolve().parent.parent

于是我就好奇,os 和 pathlib 同样是标准库,为什么 pathlib 得到了 Django 的青睐?学习了一番 pathlib 之后,发现这是一个非常高效便捷的工具,用它来处理文件系统路径相关的操作最合适不过,集成了很多快捷的功能,提升你的编程效率,那是妥妥的。

接下来让一起看一下,为什么 pathlib 更值得我们使用。

pathlib vs os

话不多说,先看下使用对比:比如说

  1. 打印当前的路径:

使用 os:

In [13]: import os

In [14]: os.getcwd()
Out[14]: '/Users/aaron'

使用 pathlib:

In [15]: from pathlib import Path

In [16]: Path.cwd()Out[16]: PosixPath('/Users/aaron')In [17]: print(Path.cwd())/Users/aaron

使用 print 打印的结果是一样的,但 os.getcwd() 返回的是字符串,而 Path.cwd() 返回的是 PosixPath 类,你还可以对此路径进行后续的操作,会很方便。

  1. 判断路径是否存在:

使用 os:

In [18]: os.path.exists('/Users/aaron/tmp')
Out[18]: True

使用 pathlib:

In [21]: tmp = Path('/Users/aaron/tmp')

In [22]: tmp.exists()Out[22]: True

可以看出 pathlib 更易读,更面向对象。

  1. 显示文件夹的内容

In [38]: os.listdir('/Users/aaron/tmp')
Out[38]: ['.DS_Store', '.hypothesis', 'b.txt', 'a.txt', 'c.py', '.ipynb_checkpoints']

In [39]: tmp.iterdir()
Out[39]: <generator object Path.iterdir at 0x7fa3f20d95f0>

In [40]: list(tmp.iterdir())
Out[40]:
[PosixPath('/Users/aaron/tmp/.DS_Store'),
 PosixPath('/Users/aaron/tmp/.hypothesis'),
 PosixPath('/Users/aaron/tmp/b.txt'),
 PosixPath('/Users/aaron/tmp/a.txt'),
 PosixPath('/Users/aaron/tmp/c.py'),
 PosixPath('/Users/aaron/tmp/.ipynb_checkpoints')]

可以看出 Path().iterdir 返回的是一个生成器,这在目录内文件特别多的时候可以大大节省内存,提升效率。

  1. 通配符支持

os 不支持含有通配符的路径,但 pathlib 可以:

In [45]: list(Path('/Users/aaron/tmp').glob('*.txt'))Out[45]: [PosixPath('/Users/aaron/tmp/b.txt'), PosixPath('/Users/aaron/tmp/a.txt')]
  1. 便捷的读写文件操作

这是 pathlib 特有的:

f = Path('test_dir/test.txt'))
f.write_text('This is a sentence.')
f.read_text()

也可以使用 with 语句:

>>> p = Path('setup.py')>>> with p.open() as f: f.readline()...'#!/usr/bin/env python3\n'
  1. 获取文件的元数据

In [56]: p = Path('/Users/aaron/tmp/c.py')

In [57]: p.stat()
Out[57]: os.stat_result(st_mode=33188, st_ino=35768389, st_dev=16777221, st_nlink=1, st_uid=501, st_gid=20, st_size=20, st_atime=1620633580, st_mtime=1620633578, st_ctime=1620633578)

In [58]: p.parts
Out[58]: ('/', 'Users', 'aaron', 'tmp', 'c.py')

In [59]: p.parent
Out[59]: PosixPath('/Users/aaron/tmp')

In [60]: p.resolve()
Out[60]: PosixPath('/Users/aaron/tmp/c.py')

In [61]: p.exists()
Out[61]: True

In [62]: p.is_dir()
Out[62]: False

In [63]: p.is_file()
Out[63]: True

In [64]: p.owner()
Out[64]: 'aaron'

In [65]: p.group()
Out[65]: 'staff'

In [66]: p.name
Out[66]: 'c.py'

In [67]: p.suffix
Out[67]: '.py'

In [68]: p.suffixes
Out[68]: ['.py']

In [69]: p.stem
Out[69]: 'c'

  1. 路径的连接 join

相比 os.path.join,使用一个 / 是不是更为直观和便捷?

>>> p = PurePosixPath('foo')>>> p / 'bar'PurePosixPath('foo/bar')>>> p / PurePosixPath('bar')PurePosixPath('foo/bar')>>> 'bar' / pPurePosixPath('bar/foo')

当然,也可以使用 joinpath 方法

>>> PurePosixPath('/etc').joinpath('passwd')
PurePosixPath('/etc/passwd')
>>> PurePosixPath('/etc').joinpath(PurePosixPath('passwd'))
PurePosixPath('/etc/passwd')
>>> PurePosixPath('/etc').joinpath('init.d', 'apache2')
PurePosixPath('/etc/init.d/apache2')
>>> PureWindowsPath('c:').joinpath('/Program Files')
PureWindowsPath('c:/Program Files')
  1. 路径匹配

>>> PurePath('a/b.py').match('*.py')True>>> PurePath('/a/b/c.py').match('b/*.py')True>>> PurePath('/a/b/c.py').match('a/*.py')False

pathlib 出现的背景和要解决的问题

pathlib 目的是提供一个简单的类层次结构来处理文件系统的路径,同时提供路径相关的常见操作。那为什么不使用 os 模块或者 os.path 来实现呢?

许多人更喜欢使用 datetime 模块提供的高级对象来处理日期和时间,而不是使用数字时间戳和 time 模块 API。同样的原因,假如使用专用类表示文件系统路径,也会更受欢迎。

换句话说,os.path 是面向过程风格的,而 pathlib 是面向对象风格的。Python 也在一直在慢慢地从复制 C 语言的 API 转变为围绕各种常见功能提供更好,更有用的抽象。

其他方面,使用专用的类处理特定的需求也是很有必要的,例如 Windows 路径不区分大小写。

在这样的背景下,pathlib 在 Python 3.4 版本加入标准库。

pathlib 的优势和劣势分别是什么

pathlib 的优势在于考虑了 Windows 路径的特殊性,同时提供了带 I/O 操作的和不带 I/O 操作的类,使用场景更加明确,API 调用更加易懂。

先看下 pathlib 对类的划分:

img

图中的箭头表示继承自,比如 Path 继承自 PurePath,PurePath 表示纯路径类,只提供路径常见的操作,但不包括实际 I/O 操作,相对安全;Path 包含 PurePath 的全部功能,包括 I/O 操作。

PurePath 有两个子类,一个是 PureWindowsPath,表示 Windows 下的路径,不区分大小写,另一个是 PurePosixPath,表示其他系统的路径。有了 PureWindowsPath,你可以这样对路径进行比较:

from pathlib import PureWindowsPath
>>> PureWindowsPath('a') == PureWindowsPath('A')
True

PurePath 可以在任何操作系统上实例化,也就是说与平台无关,你可以在 unix 系统上使用 PureWindowsPath,也可以在 Windows 系统上使用 PurePosixPath,他们还可以相互比较。

>>> from pathlib import PurePosixPath, PureWindowsPath, PosixPath  >>> PurePosixPath('a') == PurePosixPath('b')False>>> PurePosixPath('a') < PurePosixPath('b')True>>> PurePosixPath('a') == PosixPath('a')True>>> PurePosixPath('a') == PureWindowsPath('a')False

可以看出,同一个类可以相互比较,不同的类比较的结果是 False。

相反,包含 I/O 操作的类 PosixPath 及 WindowsPath 只能在对应的平台实例化:

In [8]: from pathlib import PosixPath,WindowsPath

In [9]: PosixPath('a')
Out[9]: PosixPath('a')

In [10]: WindowsPath('a')
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
<ipython-input-10-cc7a0d86d4ed> in <module>
----> 1 WindowsPath('a')

/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/pathlib.py in __new__(cls, *args, **kwargs)
   1038         self = cls._from_parts(args, init=False)
   1039         if not self._flavour.is_supported:
-> 1040             raise NotImplementedError('cannot instantiate %r on your system'
   1041                                       % (cls.__name__,))
   1042         self._init()

NotImplementedError: cannot instantiate 'WindowsPath' on your system

In [11]:

要说劣势,如果有的话,那就是在选择类时会比较困惑,到底用哪一个呢?其实如果你不太确定的话,用 Path 就可以了,这也是它的名称最短的原因,因为更加常用,短点的名称编写的更快。

适用的场景

如果要处理文件系统相关的操作,选 pathlib 就对了。

一些关键点

获取家目录:

In [70]: from pathlib import Path

In [71]: Path.home()Out[71]: PosixPath('/Users/aaron')

父目录的层级获取:

>>> p = PureWindowsPath('c:/foo/bar/setup.py')
>>> p.parents[0]
PureWindowsPath('c:/foo/bar')
>>> p.parents[1]
PureWindowsPath('c:/foo')
>>> p.parents[2]
PureWindowsPath('c:/')

获取多个文件后缀:

>>> PurePosixPath('my/library.tar.gar').suffixes['.tar', '.gar']>>> PurePosixPath('my/library.tar.gz').suffixes['.tar', '.gz']>>> PurePosixPath('my/library').suffixes[]

Windows 风格转 Posix:

>>> p = PureWindowsPath('c:\\windows')
>>> str(p)
'c:\\windows'
>>> p.as_posix()
'c:/windows'

获取文件的 uri:

>>> p = PurePosixPath('/etc/passwd')>>> p.as_uri()'file:///etc/passwd'>>> p = PureWindowsPath('c:/Windows')>>> p.as_uri()'file:///c:/Windows'

判断是否绝对路径:

>>> PurePosixPath('/a/b').is_absolute()
True
>>> PurePosixPath('a/b').is_absolute()
False

>>> PureWindowsPath('c:/a/b').is_absolute()
True
>>> PureWindowsPath('/a/b').is_absolute()
False
>>> PureWindowsPath('c:').is_absolute()
False
>>> PureWindowsPath('//some/share').is_absolute()
True

文件名若有变化:

>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')>>> p.with_name('setup.py')PureWindowsPath('c:/Downloads/setup.py')

是不是非常方便?

技术的底层原理和关键实现

pathlib 并不是基于 str 的实现,而是基于 object 设计的,这样就严格地区分了 Path 对象和字符串对象,同时也用到了一点 os 的功能,比如 os.name,os.getcwd 等,这一点大家可以看 pathlib 的源码了解更多。

最后的话

本文分享了 pathlib 的用法,后面要处理路径相关的操作时,你应该第一时间想到 pathlib,不会用没有关系,搜索引擎所搜索 pathlib 就可以看到具体的使用方法。

虽然 pathlib 比 os 库更高级,更方便并且提供了很多便捷的功能,但是我们仍然需要知道如何使用 os 库,因为 os 库是 Python 中功能最强大且最基本的库之一,但是,在需要一些文件系统操作时,强烈建议使用 pathlib。

--- EOF ---
(0)

相关推荐

  • Python十大文件骚操作!!

    来源:Python数据科学 作者:东哥起飞 日常对于批量处理文件的需求非常多,用Python写脚本可以非常方便地实现,但在这过程中难免会和文件打交道,第一次做会有很多文件的操作无从下手,只能找度娘. ...

  • pathlib:优雅的路径处理库

    玩编程好像时时刻刻都少不了跟文件路径打交道,例如爬取的数据保存到指定地方,或者分析数据时读取指定的文件. 一.常规的方法是用os库实现 获取代码当前路径,然后join当前路径后面的文件夹,再join文 ...

  • [干货分享]Python文件操作技巧总结

    原创 我的果果超可爱 脉冲功率实验室 1周前收录于话题#数学建模3#数据分析6#科技8#Python5#编程6引言小伙伴们,今天给大家讲解一下python程序下的文件操作完整技巧梳理,都是笔者总结的干 ...

  • Python3中如何检查文件是否存在?

    众所周知,Python版本分为Python2和Python3,那么你知道Python3中如何检查文件是否存在吗?常用的方法有哪些?小编为大家列举几种方法. 一. 使用os库 os库方法可检查文件是否存 ...

  • 产品原型这么做,才叫真的爽

    经常看到很多产品新人在群里问 Axure 或 Sketch 的安装包,而且要破解版的那种.说实话,我并不觉得这两款工具有多好用. 相对来说,我会觉得 Sketch 还好点,Axure 是真难用. 其实 ...

  • 爽文,真的爽一下就完事儿了?

    虽然一直不大看网文,但偶尔手贱点开一个,看着看着,就入了坑.想起好多年前,有一天,有个编辑问我:"手上有没有爽文?"啥爽文?后来说,就是主人公一路很顺很牛,读起来很爽啊. 这样一说 ...

  • 少妇自曝情史:做个“渣女”,真的爽爆了!

    休闲时光 AFTERNOON 1 2013年她与丈夫相识结婚.婚后三年一直没有孩子,她努力备孕,终于有了喜讯.但怀孕过程中,异常艰辛,竟然还查出肾功能异常,无奈只能流产. 妊娠反应孕高症诱发了她的肾炎 ...

  • 终极桌面2.0,这样的电脑桌才真的爽

    入手需求 人人家中都有一张电脑桌(或者是兼顾办公的桌子),其实电脑桌升级是一件很折腾的事情,比如说发现桌子不够太拥挤,显示器低了要加增高架,音箱低了要加增高垫,没有灯光要上RGB,久坐对身体不好要换升 ...

  • 毕业工作几年后,感叹学生党是真的爽!请珍惜

    最近收到了苹果官方推送的消息,每年苹果官网都会有教育优惠政策,没想到来得这么快,工作几年后,回想起曾经学生时代,结合现在互联网发达时期,不禁感叹道,当学生是真的很爽. 下面浩南把当学生爽的几个点分享给 ...

  • 和两位女朋友同屋住同床啪,毫无违和感!这样的家庭生活真的爽吗?

    丽莎知道, 今天,英国<每日邮报>网站刊登一条非常令人惊讶的新闻:一位英国男子,和他的两位女朋友,同住一屋,同睡一张大床,女朋友A生了一个孩子之后,女朋友B现在也怀孕了,两个女人不但没有争 ...

  • 5本近期已完结极品小说,一拿起就舍不得放下,一口气看完真的爽

    5本近期已完结极品小说,一拿起就舍不得放下,一口气看完真的爽

  • 职业规划这样回答,真的爽翻啦

    面试的时候,问到职业规划的问题,应该是大多数人最害怕的问题. 职业规划是一个大课题,别说应届生,很多工作三五年的人也不清楚自己的职业方向如何. 所以呢,如何回答这个问题,或者作为招聘狗到底想听到怎样的 ...

  • 汽车大观|想要挑战奥德赛,现代库斯途是真的飘了吗?

    自主品牌发力,成为本届成都车展的一大看点,一众国货新车的亮相令人目不暇接.唯独在家用MPV领域,赛那.嘉华和库斯途的集体登场,让合资品牌有了一丝丝的存在感.尤其是中大型MPV现代库斯途,公布了17.5 ...