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

在 3.4 版新加入.

**原始碼：**Lib/pathlib.py

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

這個模組提供了涵蓋不同作業系統中語義對等的檔案路徑類別（class）。路徑
類別被分為純路徑及具體路徑兩種，純路徑提供純粹的計算操作而不涉及輸入輸
出（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)，我們也稱之為*類型*：

class pathlib.PurePath(*pathsegments)

   一個通用的類別，表示系統的路徑類型（實例化時會建立一個
   "PurePosixPath" 或 "PureWindowsPath")：

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

   *pathsegments* 中的每個元素可以是以下三種的其中一種：一個表示路徑片
   段的字串、實作了 "os.PathLike" 介面 (interface) 並回傳字串的物件，
   或者另一個路徑物件：

      >>> 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'"）
   時，磁碟機 (drive) 部分不會被重置：

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

   不必要的斜線和單點會被合併，但雙點 ("'..'") 和前置的雙斜線 ("'//'")
   不會被合併，因為這樣會因為各種原因改變路徑的意義（例如符號連結
   (symbolic links)、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')

   （一個使得 "PurePosixPath('foo/../bar')" 等同於
   "PurePosixPath('bar')" 的單純方法，但如果 "foo" 是一個目錄的符號連
   結，這是錯誤的。）

   純路徑物件實作了 "os.PathLike" 介面，使得它們可以在任何接受該介面的
   地方使用。

   在 3.6 版的變更: 新增了對於 "os.PathLike" 介面的支援。

class pathlib.PurePosixPath(*pathsegments)

   "PurePath" 的一個子類別 (subclass)，該路徑類型表示非 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" 類似。

不論你使用的是什麼系統，你都可以實例化這些類別，因為它們不提供任何涉及
系統呼叫 (system calls) 的操作。


通用特性
--------

路徑物件是不可變 (immutable) 且 *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'


運算子
------

斜線運算子（slash operator）用於建立子路徑，就像是 "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)

   调用此方法等同于将每个 *other* 参数中的项目连接在一起:

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

   计算此路径相对 *other* 表示路径的版本。如果不可计算，则抛出
   ValueError:

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

   注意：此函数是 "PurePath" 的一部分并且适用于字符串。 它不会检查或访
   问下层的文件结构。

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

   此路径是否指向一个已存在的文件或目录:

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

   備註:

     如果路径指向一个符号链接， "exists()" 返回此符号链接是否指向存在
     的文件或目录。

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

   備註:

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

   引發一個附帶引數 "self"、"pattern" 的稽核事件 "pathlib.Path.glob"。

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

Path.group()

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

Path.is_dir()

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

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

Path.is_file()

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

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

Path.is_mount()

   如果路径是一个 *挂载点 <mount point>*: 在文件系统中被其他不同的文件
   系统挂载的地点则返回 "True"。在 POSIX 系统上，此函数检查 *path* 的
   父级 —— "path/.." 是否处于一个和 *path* 不同的设备中，或者
   "path/.." 和 *path* 是否指向相同设备的相同 i-node —— 这能检测所有
   Unix 以及 POSIX 变种上的挂载点。 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()

   將指向檔案的二進制內容以一個位元組 (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* ，並回傳一個新的路徑
   (Path) 物件指向該 *target* 。在 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'

   目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於當前的工作目錄進
   行解釋，*not* 相對於路徑物件所在的目錄。

   此功能是使用 "os.rename()" 實現的，並提供相同的保證。

   在 3.8 版的變更: 新增了回傳值，回傳新的路徑 (Path) 物件。

Path.replace(target)

   將此檔案或目錄重新命名為給定的 *target* ，並回傳一個指向 *target*
   的新路徑物件。如果 *target* 指向一個現有的檔案或空目錄，它將被無條
   件地取代。

   目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於當前的工作目錄進
   行解釋，*not* 相對於路徑物件所在的目錄。

   在 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 版本之前的行為是嚴格的）。

Path.rglob(pattern)

   這相當於在給定的相對 *pattern* 前面加上 ""**/"" 並呼叫
   "Path.glob()" ：

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

   引發一個附帶引數 "self"、"pattern" 的稽核事件 "pathlib.Path.rglob"
   。

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

Path.rmdir()

   移除此目錄。該目錄必須為空。

Path.samefile(other_path)

   回傳是否此路徑指向與 *other_path* 相同的檔案，*other_path* 可以是路
   徑 (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)

   创建硬链接 *target* 指向此路径。

   警告:

     此函数不会将此路径设为指向 *target* 的硬链接，尽管此函数名和参数
     名有此含义。 参数顺序 (target, link) 与 "Path.symlink_to()" 和
     "Path.hardlink_to()" 相反，而与 "os.link()" 的一致。

   在 3.8 版新加入.

   在 3.10 版之後被棄用: 此方法已被弃用而建议改用 "Path.hardlink_to()"
   ，因为 "Path.link_to()" 的参数顺序与 "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()" 则不要求。
