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

在 3.4 版本加入.

**源代码：**Lib/pathlib.py

======================================================================

该模块提供表示文件系统路径的类，其语义适用于不同的操作系统。路径类被分
为提供纯计算操作而没有 I/O 的 纯路径，以及从纯路径继承而来但提供 I/O
操作的 具体路径。

[图片]

如果以前从未用过此模块，或不确定哪个类适合完成任务，那要用的可能就是
"Path"。它在运行代码的平台上实例化为 具体路径。

在一些用例中纯路径很有用，例如：

1. 如果你想要在 Unix 设备上操作 Windows 路径（或者相反）。你不应在
   Unix 上实例化一个 "WindowsPath"，但是你可以实例化 "PureWindowsPath"
   。

2. 你只想操作路径但不想实际访问操作系统。在这种情况下，实例化一个纯路
   径是有用的，因为它们没有任何访问操作系统的操作。

参见: **PEP 428**：pathlib 模块 -- 面向对象的文件系统路径。

参见: 对于底层的路径字符串操作，你也可以使用 "os.path" 模块。


基础使用
========

导入主类:

   >>> from pathlib import Path

列出子目录:

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

列出当前目录树下的所有 Python 源代码文件:

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

在目录树中移动:

   >>> p = Path('/etc')
   >>> q = p / 'init.d' / 'reboot'
   >>> q
   PosixPath('/etc/init.d/reboot')
   >>> q.resolve()
   PosixPath('/etc/rc.d/init.d/halt')

查询路径的属性:

   >>> q.exists()
   True
   >>> q.is_dir()
   False

打开一个文件:

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


纯路径
======

纯路径对象提供了不实际访问文件系统的路径处理操作。有三种方式来访问这些
类，也是不同的风格：

class pathlib.PurePath(*pathsegments)

   一个通用的类，代表当前系统的路径风格（实例化为 "PurePosixPath" 或者
   "PureWindowsPath"）:

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

   Each element of *pathsegments* can be either a string representing
   a path segment, an object implementing the "os.PathLike" interface
   which returns a string, or another path object:

      >>> PurePath('foo', 'some/path', 'bar')
      PurePosixPath('foo/some/path/bar')
      >>> PurePath(Path('foo'), Path('bar'))
      PurePosixPath('foo/bar')

   当 *pathsegments* 为空的时候，假定为当前目录:

      >>> PurePath()
      PurePosixPath('.')

   如果某个段为绝对路径，则其前面的所有段都会被忽略 (类似
   "os.path.join()"):

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

   在 Windows 上，当遇到带根符号的路径段 (如 "r'\foo'") 时驱动器将不会
   被重置:

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

   假斜杠和单个点号会被消除，但双点号 ("'..'") 和打头的双斜杠 ("'//'")
   不会，因为这会出于各种原因改变路径的实际含义 (例如符号链接、UNC 路
   径等):

      >>> PurePath('foo//bar')
      PurePosixPath('foo/bar')
      >>> 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" 是一个指向其他目录的符号链接那么
   这个做法就将出错）

   纯路径对象实现了 "os.PathLike" 接口，允许它们在任何接受此接口的地方
   使用。

   在 3.6 版本发生变更: 添加了 "os.PathLike" 接口支持。

class pathlib.PurePosixPath(*pathsegments)

   一个 "PurePath" 的子类，路径风格不同于 Windows 文件系统:

      >>> PurePosixPath('/etc')
      PurePosixPath('/etc')

   *pathsegments* 参数的指定和 "PurePath" 相同。

class pathlib.PureWindowsPath(*pathsegments)

   "PurePath" 的一个子类，此路径风格代表 Windows 文件系统路径，包括
   UNC paths:

      >>> PureWindowsPath('c:/Program Files/')
      PureWindowsPath('c:/Program Files')
      >>> PureWindowsPath('//server/share/file')
      PureWindowsPath('//server/share/file')

   *pathsegments* 参数的指定和 "PurePath" 相同。

无论你正运行什么系统，你都可以实例化这些类，因为它们提供的操作不做任何
系统调用。


通用性质
--------

路径是不可变并且 *hashable*。 相同风格的路径可以排序和比较。 这此特性
会尊重对应风格的大小写转换语义。:

   >>> PurePosixPath('foo') == PurePosixPath('FOO')
   False
   >>> PureWindowsPath('foo') == PureWindowsPath('FOO')
   True
   >>> PureWindowsPath('FOO') in { PureWindowsPath('foo') }
   True
   >>> PureWindowsPath('C:') < PureWindowsPath('d:')
   True

不同风格的路径比较得到不等的结果并且无法被排序:

   >>> 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()"。 如果参数为一个绝对
路径，则之前的路径会被忽略。 在 Windows 上，当参数为一个带根符号的相对
路径 (如 "r'\foo'") 时驱动器将不会被重置:

   >>> p = PurePath('/etc')
   >>> p
   PurePosixPath('/etc')
   >>> p / 'init.d' / 'apache2'
   PurePosixPath('/etc/init.d/apache2')
   >>> q = PurePath('bin')
   >>> '/usr' / q
   PurePosixPath('/usr/bin')
   >>> p / '/an_absolute_path'
   PurePosixPath('/an_absolute_path')
   >>> PureWindowsPath('c:/Windows', '/Program Files')
   PureWindowsPath('c:/Program Files')

文件对象可用于任何接受 "os.PathLike" 接口实现的地方。

   >>> import os
   >>> p = PurePath('/etc')
   >>> os.fspath(p)
   '/etc'

路径的字符串表示法为它自己原始的文件系统路径（以原生形式，例如在
Windows 下使用反斜杠）。你可以传递给任何需要字符串形式路径的函数。

   >>> p = PurePath('/etc')
   >>> str(p)
   '/etc'
   >>> p = PureWindowsPath('c:/Program Files')
   >>> str(p)
   'c:\\Program Files'

类似地，在路径上调用 "bytes" 将原始文件系统路径作为字节对象给出，就像
被 "os.fsencode()" 编码一样:

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

备注:

  只推荐在 Unix 下调用 "bytes"。在 Windows， unicode 形式是文件系统路
  径的规范表示法。


访问个别部分
------------

为了访问路径独立的部分 （组件），使用以下特征属性：

PurePath.parts

   一个元组，可以访问路径的多个组件:

      >>> p = PurePath('/usr/bin/python3')
      >>> p.parts
      ('/', 'usr', 'bin', 'python3')

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

   （注意盘符和本地根目录是如何重组的）


方法和特征属性
--------------

纯路径提供以下方法和特征属性：

PurePath.drive

   一个表示驱动器盘符或命名的字符串，如果存在:

      >>> PureWindowsPath('c:/Program Files/').drive
      'c:'
      >>> PureWindowsPath('/Program Files/').drive
      ''
      >>> PurePosixPath('/etc').drive
      ''

   UNC 分享也被认作驱动器:

      >>> PureWindowsPath('//host/share/foo.txt').drive
      '\\\\host\\share'

PurePath.root

   一个表示（本地或全局）根的字符串，如果存在:

      >>> PureWindowsPath('c:/Program Files/').root
      '\\'
      >>> PureWindowsPath('c:Program Files/').root
      ''
      >>> PurePosixPath('/etc').root
      '/'

   UNC 分享一样拥有根:

      >>> PureWindowsPath('//host/share').root
      '\\'

   如果路径以超过两个连续斜框打头，"PurePosixPath" 会合并它们:

      >>> PurePosixPath('//etc').root
      '//'
      >>> PurePosixPath('///etc').root
      '/'
      >>> PurePosixPath('////etc').root
      '/'

   备注:

     此行为符合 *The Open Group Base Specifications Issue 6*,
     paragraph 4.11 Pathname Resolution:*"以连续两个斜杠打头的路径名可
     能会以具体实现所定义的方式被解读，但是两个以上的前缀斜杠则应当被
     当作一个斜杠来处理。"*

PurePath.anchor

   驱动器和根的联合:

      >>> PureWindowsPath('c:/Program Files/').anchor
      'c:\\'
      >>> PureWindowsPath('c:Program Files/').anchor
      'c:'
      >>> PurePosixPath('/etc').anchor
      '/'
      >>> PureWindowsPath('//host/share').anchor
      '\\\\host\\share\\'

PurePath.parents

   提供访问此路径的逻辑祖先的不可变序列:

      >>> 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:/')

   在 3.10 版本发生变更: parents 序列现在支持 *切片* 和负的索引值。

PurePath.parent

   此路径的逻辑父路径:

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

   你不能超过一个 anchor 或空路径:

      >>> p = PurePosixPath('/')
      >>> p.parent
      PurePosixPath('/')
      >>> p = PurePosixPath('.')
      >>> p.parent
      PurePosixPath('.')

   备注:

     这是一个单纯的词法操作，因此有以下行为:

        >>> p = PurePosixPath('foo/..')
        >>> p.parent
        PurePosixPath('foo')

     如果你想要向上遍历任意文件系统路径，建议首先调用 "Path.resolve()"
     以便解析符号链接并消除 "".."" 部分。

PurePath.name

   一个表示最后路径组件的字符串，排除了驱动器与根目录，如果存在的话:

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

   UNC 驱动器名不被考虑:

      >>> PureWindowsPath('//some/share/setup.py').name
      'setup.py'
      >>> PureWindowsPath('//some/share').name
      ''

PurePath.suffix

   最终组件的文件扩展名（如果有）：

      >>> PurePosixPath('my/library/setup.py').suffix
      '.py'
      >>> PurePosixPath('my/library.tar.gz').suffix
      '.gz'
      >>> PurePosixPath('my/library').suffix
      ''

PurePath.suffixes

   一个路径文件扩展名的列表：

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

PurePath.stem

   最后一个路径组件，除去后缀:

      >>> PurePosixPath('my/library.tar.gz').stem
      'library.tar'
      >>> PurePosixPath('my/library.tar').stem
      'library'
      >>> PurePosixPath('my/library').stem
      'library'

PurePath.as_posix()

   返回使用正斜杠（"/"）的路径字符串:

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

PurePath.as_uri()

   将路径表示为 "file" URI。 如果路径不是绝对路径，将引发 "ValueError"
   。

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

PurePath.is_absolute()

   返回此路径是否为绝对路径。如果路径同时拥有驱动器符与根路径（如果风
   格允许）则将被认作绝对路径。

      >>> 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_relative_to(*other)

   返回此路径是否相对于 *other* 的路径。

   >>> p = PurePath('/etc/passwd')
   >>> p.is_relative_to('/etc')
   True
   >>> p.is_relative_to('/usr')
   False

   If multiple arguments are supplied, they are joined together.

   此方法是基于字符串的；它不会访问文件系统也不会对 "".."" 部分进行特
   殊处理。 以下代码是等价的：

   >>> u = PurePath('/usr')
   >>> u == p or u in p.parents
   False

   在 3.9 版本加入.

PurePath.is_reserved()

   在 "PureWindowsPath"，如果路径是被 Windows 保留的则返回 "True"，否
   则 "False"。在 "PurePosixPath"，总是返回 "False"。

   >>> PureWindowsPath('nul').is_reserved()
   True
   >>> PurePosixPath('nul').is_reserved()
   False

   对保留路径的文件系统调用可能会莫名其妙地失败或产生意想不到的效果。

PurePath.joinpath(*other)

   Calling this method is equivalent to combining the path with each
   of the *other* arguments in turn:

      >>> 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)

   将此路径与所提供的 glob 样式匹配。如果匹配成功，则返回``True``，否
   则返回``False``。

   如果 *pattern* 是相对路径，则路径既可以是相对路径，也可以是绝对路径
   ，匹配从右边的开始：

      >>> 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

   如果 *pattern* 是绝对的，则路径必须是绝对的，并且路径必须完全匹配:

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

   与其他方法一样，是否大小写敏感遵循平台的默认规则:

      >>> PurePosixPath('b.py').match('*.PY')
      False
      >>> PureWindowsPath('b.py').match('*.PY')
      True

PurePath.relative_to(*other)

   Compute a version of this path relative to the path represented by
   *other*.  If it's impossible, ValueError is raised:

      >>> 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' is not in the subpath of '/usr' OR one path is relative and the other absolute.

   If multiple arguments are supplied, they are joined together.

   NOTE: This function is part of "PurePath" and works with strings.
   It does not check or access the underlying file structure.

PurePath.with_name(name)

   返回一个新的路径并修改 "name"。如果原本路径没有 name，ValueError 被
   抛出:

      >>> 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_stem(stem)

   返回一个带有修改后 "stem" 的新路径。 如果原路径没有名称，则会引发
   ValueError:

      >>> p = PureWindowsPath('c:/Downloads/draft.txt')
      >>> p.with_stem('final')
      PureWindowsPath('c:/Downloads/final.txt')
      >>> p = PureWindowsPath('c:/Downloads/pathlib.tar.gz')
      >>> p.with_stem('lib')
      PureWindowsPath('c:/Downloads/lib.gz')
      >>> p = PureWindowsPath('c:/')
      >>> p.with_stem('')
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
        File "/home/antoine/cpython/default/Lib/pathlib.py", line 861, in with_stem
          return self.with_name(stem + self.suffix)
        File "/home/antoine/cpython/default/Lib/pathlib.py", line 851, in with_name
          raise ValueError("%r has an empty name" % (self,))
      ValueError: PureWindowsPath('c:/') has an empty name

   在 3.9 版本加入.

PurePath.with_suffix(suffix)

   返回一个新的路径并修改 "suffix"。如果原本的路径没有后缀，新的
   *suffix* 则被追加以代替。如果 *suffix* 是空字符串，则原本的后缀被移
   除:

      >>> 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')
      >>> p = PureWindowsPath('README.txt')
      >>> p.with_suffix('')
      PureWindowsPath('README')


具体路径
========

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

class pathlib.Path(*pathsegments)

   一个 "PurePath" 的子类，此类以当前系统的路径风格表示路径（实例化为
   "PosixPath" 或 "WindowsPath"）:

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

   *pathsegments* 参数的指定和 "PurePath" 相同。

class pathlib.PosixPath(*pathsegments)

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

      >>> PosixPath('/etc')
      PosixPath('/etc')

   *pathsegments* 参数的指定和 "PurePath" 相同。

class pathlib.WindowsPath(*pathsegments)

   "Path" 和 "PureWindowsPath" 的子类，从类表示一个 Windows 文件系统的
   具体路径:

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

   *pathsegments* 参数的指定和 "PurePath" 相同。

你只能实例化与当前系统风格相同的类（允许系统调用作用于不兼容的路径风格
可能在应用程序中导致缺陷或失败）:

   >>> 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"。

在 3.8 版本发生变更: 对于包含 OS 层级无法表示字符的路径，"exists()",
"is_dir()", "is_file()", "is_mount()", "is_symlink()",
"is_block_device()", "is_char_device()", "is_fifo()", "is_socket()" 现
在将返回 "False" 而不是引发异常。

classmethod Path.cwd()

   返回一个新的表示当前目录的路径对象（和 "os.getcwd()" 返回的相同）:

      >>> Path.cwd()
      PosixPath('/home/antoine/pathlib')

classmethod Path.home()

   返回一个表示用户家目录的新路径对象（与带 "~" 构造的
   "os.path.expanduser()" 所返回的相同）。 如果无法解析家目录，则会引
   发 "RuntimeError"。

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

   在 3.5 版本加入.

Path.stat(*, follow_symlinks=True)

   返回一个 "os.stat_result" 对象，其中包含有关此路径的信息，例如
   "os.stat()"。 结果会在每次调用此方法时重新搜索。

   此方法通常会跟随符号链接；要对 symlink 使用 stat 请添加参数
   "follow_symlinks=False"，或者使用 "lstat()"。

      >>> p = Path('setup.py')
      >>> p.stat().st_size
      956
      >>> p.stat().st_mtime
      1327883547.852554

   在 3.10 版本发生变更: 增加了 *follow_symlinks* 形参。

Path.chmod(mode, *, follow_symlinks=True)

   改变文件模式和权限，和 "os.chmod()" 一样。

   此方法通常会跟随符号链接。 某些 Unix 变种支持改变 symlink 本身的权
   限；在这些平台上你可以添加参数 "follow_symlinks=False"，或者使用
   "lchmod()"。

      >>> p = Path('setup.py')
      >>> p.stat().st_mode
      33277
      >>> p.chmod(0o444)
      >>> p.stat().st_mode
      33060

   在 3.10 版本发生变更: 增加了 *follow_symlinks* 形参。

Path.exists()

   Whether the path points to an existing file or directory:

      >>> Path('.').exists()
      True
      >>> Path('setup.py').exists()
      True
      >>> Path('/etc').exists()
      True
      >>> Path('nonexistentfile').exists()
      False

   备注:

     If the path points to a symlink, "exists()" returns whether the
     symlink *points to* an existing file or directory.

Path.expanduser()

   返回带有扩展 "~" 和 "~user" 构造的新路径，与 "os.path.expanduser()"
   所返回的相同。 如果无法解析家目录，则会引发 "RuntimeError"。

      >>> p = PosixPath('~/films/Monty Python')
      >>> p.expanduser()
      PosixPath('/home/eric/films/Monty Python')

   在 3.5 版本加入.

Path.glob(pattern)

   解析相对于此路径的通配符 *pattern*，产生所有匹配的文件:

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

   pattern 的形式与 "fnmatch" 的相同，还增加了 ""**"" 表示 "此目录以及
   所有子目录，递归"。 换句话说，它启用递归通配:

      >>> sorted(Path('.').glob('**/*.py'))
      [PosixPath('build/lib/pathlib.py'),
       PosixPath('docs/conf.py'),
       PosixPath('pathlib.py'),
       PosixPath('setup.py'),
       PosixPath('test_pathlib.py')]

   备注:

     在一个较大的目录树中使用 ""**"" 模式可能会消耗非常多的时间。

   引发一个 审计事件 "pathlib.Path.glob" 并附带参数 "self", "pattern"
   。

   在 3.11 版本发生变更: 如果 *pattern* 以一个路径名称部分的分隔符结束
   ("sep" 或 "altsep") 则只返回目录。

Path.group()

   返回拥有此文件的用户组。如果文件的 GID 无法在系统数据库中找到，将抛
   出 "KeyError" 。

Path.is_dir()

   如果文件指向一个目录（或指向目录的符号链接）则返回 "True"，指向其他
   类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.is_file()

   如果文件指向一个常规文件（或指向常规文件的符号链接）则返回 "True"，
   指向其他类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.is_mount()

   Return "True" if the path is a *mount point*: a point in a file
   system where a different file system has been mounted.  On POSIX,
   the function checks whether *path*'s parent, "path/..", is on a
   different device than *path*, or whether "path/.." and *path* point
   to the same i-node on the same device --- this should detect mount
   points for all Unix and POSIX variants.  Not implemented on
   Windows.

   在 3.7 版本加入.

Path.is_symlink()

   如果路径指向符号链接则返回 "True"， 否则 "False"。

   如果路径不存在也返回 "False"；其他错误（例如权限错误）被传播。

Path.is_socket()

   如果路径指向一个 Unix socket 文件（或者指向 Unix socket 文件的符号
   链接）则返回 "True"，如果指向其他类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.is_fifo()

   如果路径指向一个先进先出存储（或者指向先进先出存储的符号链接）则返
   回 "True" ，指向其他类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.is_block_device()

   如果文件指向一个块设备（或者指向块设备的符号链接）则返回 "True"，指
   向其他类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.is_char_device()

   如果路径指向一个字符设备（或指向字符设备的符号链接）则返回 "True"，
   指向其他类型的文件则返回 "False"。

   当路径不存在或者是一个破损的符号链接时也会返回 "False"；其他错误（
   例如权限错误）被传播。

Path.iterdir()

   当路径指向一个目录时，产生该路径下的对象的路径:

      >>> p = Path('docs')
      >>> for child in p.iterdir(): child
      ...
      PosixPath('docs/conf.py')
      PosixPath('docs/_templates')
      PosixPath('docs/make.bat')
      PosixPath('docs/index.rst')
      PosixPath('docs/_build')
      PosixPath('docs/_static')
      PosixPath('docs/Makefile')

   子条目会以任意顺序生成，并且不包括特殊条目 "'.'" 和 "'..'"。 如果迭
   代器创建之后有文件在目录中被移除或添加，是否要包括该文件所对应的路
   径对象并没有明确规定。

Path.lchmod(mode)

   就像 "Path.chmod()" 但是如果路径指向符号链接则是修改符号链接的模式
   ，而不是修改符号链接的目标。

Path.lstat()

   就和 "Path.stat()" 一样，但是如果路径指向符号链接，则是返回符号链接
   而不是目标的信息。

Path.mkdir(mode=0o777, parents=False, exist_ok=False)

   新建给定路径的目录。如果给出了 *mode* ，它将与当前进程的 "umask" 值
   合并来决定文件模式和访问标志。如果路径已经存在，则抛出
   "FileExistsError"。

   如果 *parents* 为真值，任何找不到的父目录都会伴随着此路径被创建；它
   们会以默认权限被创建，而不考虑 *mode* 设置（模仿 POSIX 的 "mkdir
   -p" 命令）。

   如果 *parents* 为假值（默认），则找不到的父级目录会引发
   "FileNotFoundError"。

   如果 *exist_ok* 为 false（默认），则在目标已存在的情况下抛出
   "FileExistsError"。

   如果 *exist_ok* 为真值，则 "FileExistsError" 将不会被引发除非给定的
   路径在文件系统中已存在并且不是目录（与 POSIX "mkdir -p" 命令的行为
   相同）。

   在 3.5 版本发生变更: *exist_ok* 形参被加入。

Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)

   打开路径指向的文件，就像内置的 "open()" 函数所做的一样:

      >>> p = Path('setup.py')
      >>> with p.open() as f:
      ...     f.readline()
      ...
      '#!/usr/bin/env python3\n'

Path.owner()

   返回拥有此文件的用户名。如果文件的 UID 无法在系统数据库中找到，则抛
   出 "KeyError"。

Path.read_bytes()

   以字节对象的形式返回路径指向的文件的二进制内容:

      >>> p = Path('my_binary_file')
      >>> p.write_bytes(b'Binary file contents')
      20
      >>> p.read_bytes()
      b'Binary file contents'

   在 3.5 版本加入.

Path.read_text(encoding=None, errors=None)

   以字符串形式返回路径指向的文件的解码后文本内容。

      >>> p = Path('my_text_file')
      >>> p.write_text('Text file contents')
      18
      >>> p.read_text()
      'Text file contents'

   文件先被打开然后关闭。有和 "open()" 一样的可选形参。

   在 3.5 版本加入.

Path.readlink()

   返回符号链接所指向的路径（即 "os.readlink()" 的返回值）:

      >>> p = Path('mylink')
      >>> p.symlink_to('setup.py')
      >>> p.readlink()
      PosixPath('setup.py')

   在 3.9 版本加入.

Path.rename(target)

   将文件名目录重命名为给定的 *target*，并返回一个新的指向 *target* 的
   Path 实例。 在 Unix 上，如果 *target* 存在且为一个文件，如果用户有
   足够权限则它将被静默地替换。 在 Windows 上，如果 *target* 存在，则
   将会引发 "FileExistsError"。 *target* 可以是一个字符串或者另一个路
   径对象:

      >>> p = Path('foo')
      >>> p.open('w').write('some text')
      9
      >>> target = Path('bar')
      >>> p.rename(target)
      PosixPath('bar')
      >>> target.open().read()
      'some text'

   目标路径可能为绝对或相对路径。 相对路径将被解释为相对于当前工作目录
   ，而 *不是* 相对于 Path 对象的目录。

   它根据 "os.rename()" 实现并给出了同样的保证。

   在 3.8 版本发生变更: 添加了返回值，返回新的 Path 实例。

Path.replace(target)

   将文件或目录重命名为给定的 *target*，并返回一个新的指向 *target* 的
   Path 实例。 如果 *target* 指向一个现有文件或空目录，则它将被无条件
   地替换。

   目标路径可能为绝对或相对路径。 相对路径将被解释为相对于当前工作目录
   ，而 *不是* 相对于 Path 对象的目录。

   在 3.8 版本发生变更: 添加了返回值，返回新的 Path 实例。

Path.absolute()

   改为绝对路径，不会执行正规化或解析符号链接。 返回一个新的路径对象:

      >>> p = Path('tests')
      >>> p
      PosixPath('tests')
      >>> p.absolute()
      PosixPath('/home/antoine/pathlib/tests')

Path.resolve(strict=False)

   将路径绝对化，解析任何符号链接。返回新的路径对象:

      >>> p = Path()
      >>> p
      PosixPath('.')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib')

   "".."" 组件也将被消除（只有这一种方法这么做）:

      >>> p = Path('docs/../setup.py')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib/setup.py')

   如果路径不存在并且 *strict* 设为 "True"，则抛出 "FileNotFoundError"
   。如果 *strict* 为 "False"，则路径将被尽可能地解析并且任何剩余部分
   都会被不检查是否存在地追加。如果在解析路径上发生无限循环，则抛出
   "RuntimeError"。

   在 3.6 版本加入: 加入*strict* 参数（3.6之前的版本相当于strict值为
   True）

Path.rglob(pattern)

   This is like calling "Path.glob()" with ""**/"" added in front of
   the given relative *pattern*:

      >>> sorted(Path().rglob("*.py"))
      [PosixPath('build/lib/pathlib.py'),
       PosixPath('docs/conf.py'),
       PosixPath('pathlib.py'),
       PosixPath('setup.py'),
       PosixPath('test_pathlib.py')]

   引发一个 审计事件 "pathlib.Path.rglob" 并附带参数 "self", "pattern"
   。

   在 3.11 版本发生变更: 如果 *pattern* 以一个路径名称部分的分隔符结束
   ("sep" 或 "altsep") 则只返回目录。

Path.rmdir()

   移除此目录。此目录必须为空的。

Path.samefile(other_path)

   返回此目录是否指向与可能是字符串或者另一个路径对象的 *other_path*
   相同的文件。语义类似于 "os.path.samefile()" 与 "os.path.samestat()"
   。

   如果两者都以同一原因无法访问，则抛出 "OSError"。

      >>> p = Path('spam')
      >>> q = Path('eggs')
      >>> p.samefile(q)
      False
      >>> p.samefile('spam')
      True

   在 3.5 版本加入.

Path.symlink_to(target, target_is_directory=False)

   使该路径成为一个指向 *target* 的符号连接。

   在 Windows 上，符号链接可以表示文件或目录两种类型，并且不会动态改变
   类型。如果目标存在，则新建链接的类型将与目标一致。否则，如果
   *target_is_directory* 为 "True"，则符号链接将创建为目录链接，为
   "False" （默认）将创建为文件链接。在非 Windows 平台上，
   *target_is_directory* 被忽略。

      >>> p = Path('mylink')
      >>> p.symlink_to('setup.py')
      >>> p.resolve()
      PosixPath('/home/antoine/pathlib/setup.py')
      >>> p.stat().st_size
      956
      >>> p.lstat().st_size
      8

   备注:

     参数的顺序（link, target) 和 "os.symlink()" 是相反的。

Path.hardlink_to(target)

   将此路径设为一个指向与 *target* 相同文件的硬链接。

   备注:

     参数顺序 (link, target) 和 "os.link()" 是相反的。

   在 3.10 版本加入.

Path.link_to(target)

   Make *target* a hard link to this path.

   警告:

     This function does not make this path a hard link to *target*,
     despite the implication of the function and argument names. The
     argument order (target, link) is the reverse of
     "Path.symlink_to()" and "Path.hardlink_to()", but matches that of
     "os.link()".

   在 3.8 版本加入.

   自 3.10 版本弃用: This method is deprecated in favor of
   "Path.hardlink_to()", as the argument order of "Path.link_to()"
   does not match that of "Path.symlink_to()".

Path.touch(mode=0o666, exist_ok=True)

   将给定的路径创建为文件。如果给出了 *mode* 它将与当前进程的 "umask"
   值合并以确定文件的模式和访问标志。如果文件已经存在，则当 *exist_ok*
   为 true 则函数仍会成功（并且将它的修改事件更新为当前事件），否则抛
   出 "FileExistsError"。

Path.unlink(missing_ok=False)

   移除此文件或符号链接。如果路径指向目录，则用 "Path.rmdir()" 代替。

   如果 *missing_ok* 为假值（默认），则如果路径不存在将会引发
   "FileNotFoundError"。

   如果 *missing_ok* 为真值，则 "FileNotFoundError" 异常将被忽略（和
   POSIX "rm -f" 命令的行为相同）。

   在 3.8 版本发生变更: 增加了 *missing_ok* 形参。

Path.write_bytes(data)

   将文件以二进制模式打开，写入 *data* 并关闭:

      >>> p = Path('my_binary_file')
      >>> p.write_bytes(b'Binary file contents')
      20
      >>> p.read_bytes()
      b'Binary file contents'

   一个同名的现存文件将被覆盖。

   在 3.5 版本加入.

Path.write_text(data, encoding=None, errors=None, newline=None)

   将文件以文本模式打开，写入 *data* 并关闭:

      >>> p = Path('my_text_file')
      >>> p.write_text('Text file contents')
      18
      >>> p.read_text()
      'Text file contents'

   同名的现有文件会被覆盖。 可选形参的含义与 "open()" 的相同。

   在 3.5 版本加入.

   在 3.10 版本发生变更: 增加了 *newline* 形参。


对应的 "os" 模块的工具
======================

以下是一个映射了 "os" 与 "PurePath"/"Path" 对应相同的函数的表。

备注:

  以下函数/方法对并不全都是等价的。 在它们之中，有的虽然具有相互重叠的
  使用场景，但其语义有所不同。 这包括 "os.path.abspath()" 与
  "Path.absolute()", "os.path.relpath()" 与 "PurePath.relative_to()"。

+--------------------------------------+-----------------------------------+
| "os" 和 "os.path"                    | "pathlib"                         |
|======================================|===================================|
| "os.path.abspath()"                  | "Path.absolute()" [1]             |
+--------------------------------------+-----------------------------------+
| "os.path.realpath()"                 | "Path.resolve()"                  |
+--------------------------------------+-----------------------------------+
| "os.chmod()"                         | "Path.chmod()"                    |
+--------------------------------------+-----------------------------------+
| "os.mkdir()"                         | "Path.mkdir()"                    |
+--------------------------------------+-----------------------------------+
| "os.makedirs()"                      | "Path.mkdir()"                    |
+--------------------------------------+-----------------------------------+
| "os.rename()"                        | "Path.rename()"                   |
+--------------------------------------+-----------------------------------+
| "os.replace()"                       | "Path.replace()"                  |
+--------------------------------------+-----------------------------------+
| "os.rmdir()"                         | "Path.rmdir()"                    |
+--------------------------------------+-----------------------------------+
| "os.remove()", "os.unlink()"         | "Path.unlink()"                   |
+--------------------------------------+-----------------------------------+
| "os.getcwd()"                        | "Path.cwd()"                      |
+--------------------------------------+-----------------------------------+
| "os.path.exists()"                   | "Path.exists()"                   |
+--------------------------------------+-----------------------------------+
| "os.path.expanduser()"               | "Path.expanduser()" 和            |
|                                      | "Path.home()"                     |
+--------------------------------------+-----------------------------------+
| "os.listdir()"                       | "Path.iterdir()"                  |
+--------------------------------------+-----------------------------------+
| "os.path.isdir()"                    | "Path.is_dir()"                   |
+--------------------------------------+-----------------------------------+
| "os.path.isfile()"                   | "Path.is_file()"                  |
+--------------------------------------+-----------------------------------+
| "os.path.islink()"                   | "Path.is_symlink()"               |
+--------------------------------------+-----------------------------------+
| "os.link()"                          | "Path.hardlink_to()"              |
+--------------------------------------+-----------------------------------+
| "os.symlink()"                       | "Path.symlink_to()"               |
+--------------------------------------+-----------------------------------+
| "os.readlink()"                      | "Path.readlink()"                 |
+--------------------------------------+-----------------------------------+
| "os.path.relpath()"                  | "PurePath.relative_to()" [2]      |
+--------------------------------------+-----------------------------------+
| "os.stat()"                          | "Path.stat()", "Path.owner()",    |
|                                      | "Path.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.stem" 和                |
|                                      | "PurePath.suffix"                 |
+--------------------------------------+-----------------------------------+

-[ 备注 ]-

[1] "os.path.abspath()" 会对结果路径执行正规化，当存在符号链接时这可能
    改变其含义，而 "Path.absolute()" 则不会。

[2] "PurePath.relative_to()" 要求 "self" 为参数的子路径，但
    "os.path.relpath()" 则不要求。
