logo头像
Snippet 博客主题

面向对象的文件系统路径-pathlib

该模块提供表示文件系统路径的类,其语义适用于不同的操作系统。 pathlib类在纯路径之间划分,纯路径提供纯粹的计算操作而没有I / O,以及具体路径,它继承纯路径但也提供I / O操作。

如果你之前从未使用过此模块,或者只是不确定哪个类适合你的任务,那么Path很可能就是你所需要的。 为运行代码的平台提供了实例化的具体路径。

纯路径在某些特殊情况下很有用; 例如:

  1. 如果要在Unix计算机上操作Windows路径(反之亦然)。 在Unix上运行时无法实例化WindowsPath,但可以实例化PureWindowsPath。
  2. 你希望确保你的代码仅操作路径而不实际访问操作系统。 在这种情况下,实例化其中一个纯类可能很有用,因为那些只是没有任何操作系统访问操作。

基础使用

导入主类:

1
>>> from pathlib import Path

列出子目录

1
2
3
4
>>> p = Path('.')
>>> [x for x in p.iterdir() if x.is_dir()]
[PosixPath('.hg'), PosixPath('docs'), PosixPath('dist'),
PosixPath('__pycache__'), PosixPath('build')]

在此目录树中列出Python源文件

1
2
3
>>> list(p.glob('**/*.py'))
[PosixPath('test_pathlib.py'), PosixPath('setup.py'),
PosixPath('pathlib.py'), PosixPath('docs/conf.py'),PosixPath('build/lib/pathlib.py')]

在根目录插入目录树

1
2
3
4
5
6
>>> p = Path('/etc')
>>> q = p / 'init.d' / 'reboot'
>>> q
PosixPath('/etc/init.d/reboot')
>>> q.resolve()
PosixPath('/etc/rc.d/init.d/halt')

查询目录属性

1
2
3
4
>>> q.exists()
True
>>> q.is_dir()
False

打开一个文件

1
2
3
>>> with q.open() as f: f.readline()
...
'#!/bin/bash\n'

Pure paths

Pure path 对象提供了实际上不访问文件系统的路径处理操作。 有三种方法可以访问这些类,我们也称之为flavours

class pathlib.PurePath(*pathsegments)

表示系统路径风格的泛型类(实例化它会创建PurePosixPath或PureWindowsPath)

1
2
>>> PurePath('setup.py')      # Running on a Unix machine
PurePosixPath('setup.py')

每个路径元素可以是一个表示路径段的字符串,一个实现操作系统的对象。返回字符串或其他路径对象的PathLike接口:

1
2
3
4
>>> PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar')
>>> PurePath(Path('foo'), Path('bar'))
PurePosixPath('foo/bar')

当路径记录为空, 则默认当前目录

1
2
>>> PurePath()
PurePosixPath('.')

当给出几个绝对路径时,最后一个被选为一个锚(模仿os.path.join()的行为)

1
2
3
4
>>> PurePath('/etc', '/usr', 'lib64')
PurePosixPath('/usr/lib64')
>>> PureWindowsPath('c:/Windows', 'd:bar')
PureWindowsPath('d:bar')

但是,在Windows路径中,更改本地根目录并不丢弃以前的驱动器设置

1
2
>>> PureWindowsPath('c:/Windows', '/Program Files')
PureWindowsPath('c:/Program Files')

双斜线和单点会折叠,但双点(’..’)则不会,因为这将在符号链接面前改变一条路径的含义:

1
2
3
4
5
6
>>> PurePath('foo//bar')
PurePosixPath('foo/bar')
>>> PurePath('foo/./bar')
PurePosixPath('foo/bar')
>>> PurePath('foo/../bar')
PurePosixPath('foo/../bar')

(naïve方法将使PurePosixPath(’foo/../bar’)等同于PurePosixPath(’bar’),如果foo是指向另一个目录的符号链接,则该方法是错误的)

Pure path对象是实现os.PathLike接口,允许在接受接口的任何地方使用它们

版本3.6中已更改:添加了对os.PathLike接口的支持。

class pathlib.PurePosixPath(*pathsegments)

作为PurePath的子类,此路径样式表示非Windows文件系统路径

1
2
 >>> PurePosixPath('/etc')
PurePosixPath('/etc')

路径指定类似于PurePath

class pathlib.PureWindowsPath(*pathsegments)

作为PurePath的子类,此路径样式表示Windows文件系统路径

1
2
>>> PureWindowsPath('c:/Program Files/')
PureWindowsPath('c:/Program Files')

路径指定类似于PurePath

无论运行的是哪个系统,都可以实例化所有这些类,因为它们不提供任何进行系统调用的操作

一般的属性

路径是不可变的和可散列的。同一种风格的路径是可比较和可排序的。这些属性尊重风格的大小写和语义:

1
2
3
4
5
6
7
8
>>> PurePosixPath('foo') == PurePosixPath('FOO')
False
>>> PureWindowsPath('foo') == PureWindowsPath('FOO')
True
>>> PureWindowsPath('FOO') in { PureWindowsPath('foo') }
True
>>> PureWindowsPath('C:') < PureWindowsPath('d:')
True

不同风格的路径不能比较,不能排序

1
2
3
4
5
6
>>> PureWindowsPath('foo') == PurePosixPath('foo')
False
>>> PureWindowsPath('foo') < PurePosixPath('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: '<' not supported between instances of 'PureWindowsPath' and 'PurePosixPath'

操作

斜杠操作符帮助创建子路径, 类似os.path.join()

1
2
3
4
5
6
7
8
>>> p = PurePath('/etc')
>>> p
PurePosixPath('/etc')
>>> p / 'init.d' / 'apache2'
PurePosixPath('/etc/init.d/apache2')
>>> q = PurePath('bin')
>>> '/usr' / q
PurePosixPath('/usr/bin')

路径对象可以用任何os.PathLike可接受的接口的地方

1
2
3
4
>>> import os
>>> p = PurePath('/etc')
>>> os.fspath(p)
'/etc'

路径的字符串表示形式是原始文件系统路径本身(以本机形式,例如Windows下的反斜杠),你可以将它传递给任何将文件路径作为字符串的函数

1
2
3
4
5
6
>>> p = PurePath('/etc')
>>> str(p)
'/etc'
>>> p = PureWindowsPath('c:/Program Files')
>>> str(p)
'c:\\Program Files'

类似地,在路径上调用字节会将原始文件系统路径作为字节对象提供,如os.fsencode()所编码的那样

1
2
>>> bytes(p)
b'/etc'

注意:只建议在Unix下调用字节。在Windows下,unicode表单是文件系统路径的规范化表示形式。

对组件的访问

若要访问路径的各个“部件”(组件),请使用以下属性

PurePath.parts

一个元组,用于访问路径的各个组件

1
2
3
4
5
6
7
>>> p = PurePath('/usr/bin/python3')
>>> p.parts
('/', 'usr', 'bin', 'python3')

>>> p = PureWindowsPath('c:/Program Files/PSF')
>>> p.parts
('c:\\', 'Program Files', 'PSF')

(注意驱动器和本地根目录是如何在单个部件中重新分组的)

UNC 分享也被认为是驱动

1
2
>>> PureWindowsPath('//host/share/foo.txt').drive
'\\\\host\\share'
PurePath.root

一个字符串,表示(本地或全局)根目录(如果有的话)

1
2
3
4
5
6
>>> PureWindowsPath('c:/Program Files/').root
'\\'
>>> PureWindowsPath('c:Program Files/').root
''
>>> PurePosixPath('/etc').root
'/'

NUC 分享也总有一个根目录

1
2
>>> PureWindowsPath('//host/share').root
'\\'
PurePath.anchor

驱动和根目录的连接

1
2
3
4
5
6
7
8
>>> PureWindowsPath('c:/Program Files/').anchor
'c:\\'
>>> PureWindowsPath('c:Program Files/').anchor
'c:'
>>> PurePosixPath('/etc').anchor
'/'
>>> PureWindowsPath('//host/share').anchor
'\\\\host\\share\\'
PurePath.parents

一个不可变序列提供对路径逻辑父级目录的访问

1
2
3
4
5
6
7
>>> 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:/')
PurePath.parent

父级目录

1
2
3
>>> p = PurePosixPath('/a/b/c/d')
>>> p.parent
PurePosixPath('/a/b/c')

你不能通过锚定或者一个空目录

1
2
3
4
5
6
>>> p = PurePosixPath('/')
>>> p.parent
PurePosixPath('/')
>>> p = PurePosixPath('.')
>>> p.parent
PurePosixPath('.')
PurePath.name

一个字符串表示最终路径目录(如果有的话),不包括驱动器和根目录

1
2
>>> PurePosixPath('my/library/setup.py').name
'setup.py'

不考虑UNC驱动器名

1
2
3
4
>>> PureWindowsPath('//some/share/setup.py').name
'setup.py'
>>> PureWindowsPath('//some/share').name
''
PurePath.suffix

最终的文件扩展名(如果有的话)

1
2
3
4
5
6
>>> PurePosixPath('my/library/setup.py').suffix
'.py'
>>> PurePosixPath('my/library.tar.gz').suffix
'.gz'
>>> PurePosixPath('my/library').suffix
''
PurePath.suffixes

路径的扩展名的列表

1
2
3
4
5
6
>>> PurePosixPath('my/library.tar.gar').suffixes
['.tar', '.gar']
>>> PurePosixPath('my/library.tar.gz').suffixes
['.tar', '.gz']
>>> PurePosixPath('my/library').suffixes
[]
PurePath.stem

最终路径的零件, 没有扩展名

1
2
3
4
5
6
>>> PurePosixPath('my/library.tar.gz').stem
'library.tar'
>>> PurePosixPath('my/library.tar').stem
'library'
>>> PurePosixPath('my/library').stem
'library'
PurePath.as_posix()

返回带有斜杠的路径的字符串表示形式(/)

1
2
3
4
5
>>> p = PureWindowsPath('c:\\windows')
>>> str(p)
'c:\\windows'
>>> p.as_posix()
'c:/windows'
PurePath.as_uri()

将路径表示为一个文件URI。如果路径不是绝对的,则引发ValueError。

1
2
3
4
5
6
>>> p = PurePosixPath('/etc/passwd')
>>> p.as_uri()
'file:///etc/passwd'
>>> p = PureWindowsPath('c:/Windows')
>>> p.as_uri()
'file:///c:/Windows'
PurePath.is_absolute()

无论路径是否绝对,都返回。如果路径同时具有根和(如果允许)驱动器,则认为它是绝对路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> 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
PurePath.is_reserved()

对于PureWindowsPath,如果路径被认为是在Windows下保留的,则返回True,否则返回False 使用PurePosixPath时,False总是返回。

1
2
3
4
>>> PureWindowsPath('nul').is_reserved()
True
>>> PurePosixPath('nul').is_reserved()
False

保留路径上的文件系统调用可能会神秘地失败或产生意外的结果。

PurePath.joinpath(*other)

调用此方法相当于依次将路径与其他参数组合在一起。

1
2
3
4
5
6
7
8
>>> 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')
PurePath.match(pattern)

将此路径与提供的全局样式模式匹配。如果匹配成功,则返回真。否则为假。

如果模式是相对的,路径可以是相对的,也可以是绝对的,匹配可以从右边进行。

1
2
3
4
5
6
>>> 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

如果模式是绝对的,那么路径必须是绝对的,并且整个路径必须匹配:

1
2
3
4
>>> PurePath('/a.py').match('/*.py')
True
>>> PurePath('a/b.py').match('/*.py')
False

和其他方法一样,个案敏感性是观察到的,例如:

1
2
>>> PureWindowsPath('b.py').match('*.PY')
True
PurePath.relative_to(*other)

对象所表示的路径相对于此路径的版本。如果不可能,则引发ValueError:

1
2
3
4
5
6
7
8
9
10
11
>>> p = PurePosixPath('/etc/passwd')
>>> p.relative_to('/')
PurePosixPath('etc/passwd')
>>> p.relative_to('/etc')
PurePosixPath('passwd')
>>> p.relative_to('/usr')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 694, in relative_to
.format(str(self), str(formatted)))
ValueError: '/etc/passwd' does not start with '/usr'
PurePath.with_name(name)

返回一个已更改名称的新路径。如果原始路径没有名称,则引发ValueError。

1
2
3
4
5
6
7
8
9
10
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.with_name('setup.py')
PureWindowsPath('c:/Downloads/setup.py')
>>> p = PureWindowsPath('c:/')
>>> p.with_name('setup.py')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/antoine/cpython/default/Lib/pathlib.py", line 751, in with_name
raise ValueError("%r has an empty name" % (self,))
ValueError: PureWindowsPath('c:/') has an empty name
PurePath.with_suffix(suffix)

返回一个新路径,其中后缀已更改。如果原始路径没有后缀,则会追加新的后缀。

1
2
3
4
5
6
>>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
>>> p.with_suffix('.bz2')
PureWindowsPath('c:/Downloads/pathlib.tar.bz2')
>>> p = PureWindowsPath('README')
>>> p.with_suffix('.txt')
PureWindowsPath('README.txt')

Concrete paths

具体路径是纯路径类的子类。除了后者提供的操作之外,它们还提供对路径对象执行系统调用的方法。有三种方法可以实例化具体路径:

class pathlib.Path(*pathsegments)

这个类是PurePath的一个子类,表示系统路径味道的具体路径(实例化它可以创建PosixPath或WindowsPath):

1
2
>>> Path('setup.py')
PosixPath('setup.py')

路径指定类似于PurePath。

class pathlib.PosixPath(*pathsegments)

Path和PurePosixPath的一个子类,这个类表示具体的非Windows文件系统路径:

1
2
>>> PosixPath('/etc')
PosixPath('/etc')

路径指定类似于PurePath。

class pathlib.WindowsPath(*pathsegments)

这个类是Path和PureWindowsPath的子类,它表示具体的Windows文件系统路径:

1
2
>>> WindowsPath('c:/Program Files/')
WindowsPath('c:/Program Files')

路径指定类似于PurePath。

你只能实例化与你的系统对应的类风格(允许系统调用不兼容的路径,可能会导致应用程序中的错误或故障):

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import os
>>> os.name
'posix'
>>> Path('setup.py')
PosixPath('setup.py')
>>> PosixPath('setup.py')
PosixPath('setup.py')
>>> WindowsPath('setup.py')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 798, in __new__
% (cls.__name__,))
NotImplementedError: cannot instantiate 'WindowsPath' on your system

方法

除了纯路径方法外,具体路径还提供以下方法。如果系统调用失败(例如,路径不存在),这些方法中的许多都会引发OSError。

classmethod* Path.cwd()

返回一个表示当前目录的新路径对象(由os.getcwd()返回):

1
2
>>> Path.cwd()
PosixPath('/home/antoine/pathlib')
classmethod Path.hom()

返回一个新的路径对象,该对象表示用户的主目录(由os.path.expanduser()返回,带有~结构):

1
2
>>> Path.home()
PosixPath('/home/antoine')

New in version 3.5.

Path.stat()

返回关于此路径的信息(类似于os.stat())。结果在每次调用这个方法时都会被查询出来。

1
2
3
4
5
>>> p = Path('setup.py')
>>> p.stat().st_size
956
>>> p.stat().st_mtime
1327883547.852554
Path.chmod(mode)

更改文件模式和权限,如os.chmod():

1
2
3
4
5
6
>>> p = Path('setup.py')
>>> p.stat().st_mode
33277
>>> p.chmod(0o444)
>>> p.stat().st_mode
33060
Path.exists()

该路径是否指向现有的文件或目录:

1
2
3
4
5
6
7
8
>>> Path('.').exists()
True
>>> Path('setup.py').exists()
True
>>> Path('/etc').exists()
True
>>> Path('nonexistentfile').exists()
False

注意:如果路径指向符号链接,则存在()返回符号链接指向的是现有的文件还是目录。

Path.expanduser()

返回一个新路径,其中包含展开的~和~user构造,由os.path.expanduser()返回:

1
2
3
>>> p = PosixPath('~/films/Monty Python')
>>> p.expanduser()
PosixPath('/home/eric/films/Monty Python')
Path.glob(pattern)

将此路径所表示的目录中的给定模式全局化,生成所有匹配的文件(任何类型的):

1
2
3
4
>>> sorted(Path('.').glob('*.py'))
[PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]
>>> sorted(Path('.').glob('*/*.py'))
[PosixPath('docs/conf.py')]

“**”模式意味着“此目录和所有子目录,递归地”。换句话说,它支持递归全局化:

1
2
3
4
5
6
>>> sorted(Path('.').glob('**/*.py'))
[PosixPath('build/lib/pathlib.py'),
PosixPath('docs/conf.py'),
PosixPath('pathlib.py'),
PosixPath('setup.py'),
PosixPath('test_pathlib.py')]

注意:在大型目录树中使用“**”模式可能消耗大量的时间。

Path.group()

返回拥有该文件的组的名称。如果文件的gid在系统数据库中没有找到,则会引发KeyError。

Path.is_dir()

返回True如果路径指向一个目录(或指向一个目录的符号链接),则False指向另一种文件。如果路径不存在或符号链接已损坏,也会返回False;其他错误(如权限错误)也会被传播。

Path.is_file()

返回真如果路径指向常规文件(或指向常规文件的符号链接),则Falseif指向另一种文件。如果路径不存在或符号链接已损坏,也会返回False;其他错误(如权限错误)也会被传播。

Path.is_mount()

如果路径是一个挂载点,返回True:文件系统中已挂载不同文件系统的点。在POSIX上,函数检查路径的父路径/..,是否在与路径不同的设备上,或者路径/..,路径指向同一设备上的同一个i节点 —这应该可以检测所有Unix和POSIX变体的挂载点。没有在Windows上实现。

评论系统未开启,无法评论!