"os.path" --- 常見的路徑名操作
******************************

**原始碼：** Lib/posixpath.py (用於 POSIX 系統) 和 Lib/ntpath.py (用於
Windows).

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

該模組實現了一些有用的路徑名操作函式。若要讀取或寫入檔案，請參閱
"open()" 函數，要存取檔案系統，請參閱 "os" 模組。路徑參數可以以字串、
位元組或任何依照 "os.PathLike" 協議實作的物件傳遞。

與 Unix shell 不同，Python 不會*自動*進行路徑展開（path expansions）。
當應用程式需要進行類似 shell 的路徑展開時，可以明確地呼叫
"expanduser()" 和 "expandvars()" 等函式。（另請參閱 "glob" 模組。）

也參考: "pathlib" 模組提供了高階的路徑物件。

備註:

  所有這些函數都只接受位元組或字串物件作為參數。如果回傳的是路徑或檔案
  名稱，結果將是相同型別的物件。

備註:

  由於不同的作業系統具有不同的路徑命名慣例，在標準函式庫中的路徑模組有
  數個版本可供使用，而 "os.path" 模組都會是運行 Python 之作業系統所適
  用本地路徑。然而，如果你想要操作*始終*以某個不同於本機格式表示的路徑
  ，你也可以引入並使用對應的模組。它們都具有相同的介面：

  * "posixpath" 用於 UNIX 形式的路徑

  * "ntpath" 用於 Windows 的路徑

在 3.8 版的變更: 對於包含有作業系統層級無法表示之字元或位元組的路徑，
"exists()"、"lexists()"、"isdir()"、"isfile()"、"islink()" 和
"ismount()" 函式現在會回傳 "False"，而不是引發例外。

os.path.abspath(path)

   回傳經正規化的絕對路徑名 *path* 。在大多數平台上，這等效於按照以下
   方式呼叫 "normpath()" 函式："normpath(join(os.getcwd(), path))"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.basename(path)

   回傳路徑名 *path* 的基底名稱。這是將 *path* 傳遞給函式 "split()" 後
   回傳結果中的第二個元素。請注意，此函式的結果與 Unix 的 **basename**
   程式不同；對於 "'/foo/bar/'"，**basename** 回傳 "'bar'"，而
   "basename()" 函式回傳空字串（"''"）。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.commonpath(paths)

   回傳序列 *paths* 中每個路徑名的最長共同子路徑。如果 *paths* 同時包
   含絕對路徑和相對路徑、*paths* 位於不同的磁碟機或 *paths* 為空，則引
   發 "ValueError"。與 "commonprefix()" 不同，此函式回傳的是有效路徑。

   適用：Unix、Windows。

   在 3.5 版新加入.

   在 3.6 版的變更: 接受一個*類路徑物件*的序列。

os.path.commonprefix(list)

   返回作为 *list* 中所有路径前缀的最长字符串前缀（逐字符比较）。 如果
   *list* 为空，则返回空字符串 ("''")。

   警告:

     此函数可能返回无效的路径因为它是按每个字符来处理的。 如果你需要的
     是 **共同路径前缀**，则此函数中的实现算法是不安全的 。请使用
     "commonpath()" 来获取共同路径前缀。

        >>> os.path.commonprefix(['/usr/lib', '/usr/local/lib'])
        '/usr/l'

        >>> os.path.commonpath(['/usr/lib', '/usr/local/lib'])
        '/usr'

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.dirname(path)

   回傳路徑名 *path* 的目錄名稱。這是將 *path* 傳遞給函式 "split()" 後
   回傳之成對結果中的第一個元素。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.exists(path)

   如果 *path* 是一個存在的路徑或一個開啟的檔案描述器則回傳 "True"。對
   於已損壞的符號連結則回傳 "False"。在某些平台上，即使 *path* 實際存
   在，如果未被授予執行 "os.stat()" 的權限，此函式仍可能回傳 "False"。

   在 3.3 版的變更: 現在 *path* 可以是一個整數：如果它是一個開啟的檔案
   描述器，則回傳 "True"；否則回傳 "False"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.lexists(path)

   如果 *path* 是一個存在的路徑則回傳 "True"。對於已損壞的符號連結也回
   傳 "True"。在缺乏 "os.lstat()" 的平台上，與 "exists()" 函式等效。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.expanduser(path)

   在 Unix 和 Windows 上，將引數中以 "~" 或 "~user" 開頭的部分替換為該
   *user* 的家目錄。

   在 Unix 上，如果環境變數 "HOME" 有被設置，則將初始的 "~" 替換為該變
   數的值；否則將使用內建模組 "pwd" 在密碼目錄中查找當前使用者的家目錄
   。對於初始的 "~user"，直接在密碼目錄中查找該使用者的家目錄。

   在 Windows 上，如果 "USERPROFILE" 有被設置，則使用該變數的值；否則
   將結合 "HOMEPATH" 和 "HOMEDRIVE"。對於初始的 "~user"，會檢查當前使
   用者的家目錄的最後一個目錄元件是否與 "USERNAME" 相符，如果相符則替
   換它。

   如果展開失敗或路徑不以波浪符號（tilde）開頭，則回傳原始路徑，不做任
   何變更。

   在 3.6 版的變更: 接受一個 *path-like object*。

   在 3.8 版的變更: 在 Windows 上不再使用 "HOME" 變數。

os.path.expandvars(path)

   输入带有环境变量的路径作为参数，返回展开变量以后的路径。"$name" 或
   "${name}" 形式的子字符串被环境变量 *name* 的值替换。格式错误的变量
   名称和对不存在变量的引用保持不变。

   在 Windows 上，除了 "$name" 和 "${name}" 外，还可以展开 "%name%"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.getatime(path)

   返回 *path* 的最后访问时间。返回值是一个浮点数，为纪元秒数（参见
   "time" 模块）。如果该文件不存在或不可访问，则抛出 "OSError" 异常。

os.path.getmtime(path)

   返回 *path* 的最后修改时间。返回值是一个浮点数，为纪元秒数（参见
   "time" 模块）。如果该文件不存在或不可访问，则抛出 "OSError" 异常。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.getctime(path)

   返回 *path* 在系统中的 ctime，在有些系统（比如 Unix）上，它是元数据
   的最后修改时间，其他系统（比如 Windows）上，它是 *path* 的创建时间
   。返回值是一个数，为纪元秒数（参见 "time" 模块）。如果该文件不存在
   或不可访问，则抛出 "OSError" 异常。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.getsize(path)

   返回 *path* 的大小，以字节为单位。如果该文件不存在或不可访问，则抛
   出 "OSError" 异常。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.isabs(path)

   如果 *path* 是一个绝对路径，则返回 "True"。在 Unix 上，它就是以斜杠
   开头，而在 Windows 上，它可以是去掉驱动器号后以斜杠（或反斜杠）开头
   。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.isfile(path)

   如果 *path* 是 "现有的" 常规文件，则返回 "True"。本方法会跟踪符号链
   接，因此，对于同一路径，"islink()" 和 "isfile()" 都可能为 "True"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.isdir(path)

   如果 *path* 是 "现有的" 目录，则返回 "True"。本方法会跟踪符号链接，
   因此，对于同一路径，"islink()" 和 "isdir()" 都可能为 "True"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.islink(path)

   如果 *path* 指向的 "现有" 目录条目是一个符号链接，则返回 "True"。如
   果 Python 运行时不支持符号链接，则总是返回 "False"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.ismount(path)

   如果路径 *path* 是 *挂载点* （文件系统中挂载其他文件系统的点），则
   返回 "True"。在 POSIX 上，该函数检查 *path* 的父目录 "*path*/.." 是
   否在与 *path* 不同的设备上，或者 "*path*/.." 和 *path* 是否指向同一
   设备上的同一 inode（这一检测挂载点的方法适用于所有 Unix 和 POSIX 变
   体）。本方法不能可靠地检测同一文件系统上的绑定挂载 (bind mount)。在
   Windows 上，盘符和共享 UNC 始终是挂载点，对于任何其他路径，将调用
   "GetVolumePathName" 来查看它是否与输入的路径不同。

   在 3.4 版新加入: 支持在 Windows 上检测非根挂载点。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.join(path, *paths)

   智能地合并一个或多个路径部分。 返回值将是 *path* 和所有 **paths* 成
   员的拼接，其中每个非空部分后面都紧跟一个目录分隔符，最后一个除外。
   也就是说，如果最后一个部分为空或是以一个分隔符结束则结果将仅以一个
   分隔符结束。 如果某个部分为绝对路径（在 Windows 上需要同时有驱动器
   号和根路径符号），则之前的所有部分会被忽略并从该绝对路径部分开始拼
   接。

   在 Windows，当遇到绝对路径部分 (如 "r'\foo'") 时驱动器号将不会被重
   置。 如果某个部分位于不同驱动器或为绝对路径，则之前的所有部分会被忽
   略并且该驱动器号会被重置。 请注意由于每个驱动器都有一个当前目录，因
   此 "os.path.join("c:", "foo")" 是代表驱动器 "C:" 上当前路径的相对路
   径 ("c:foo")，而不是 "c:\foo"。

   在 3.6 版的變更: 接受一个 *类路径对象* 用于 *path* 和 *paths* 。

os.path.normcase(path)

   规范路径的大小写。在 Windows 上，将路径中的所有字符都转换为小写，并
   将正斜杠转换为反斜杠。在其他操作系统上返回原路径。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.normpath(path)

      通过折叠多余的分隔符和对上级目录的引用来标准化路径名，所以
      "A//B"、"A/B/"、"A/./B" 和 "A/foo/../B" 都会转换成 "A/B"。这个字
      符串操作可能会改变带有符号链接的路径的含义。在 Windows 上，本方
      法将正斜杠转换为反斜杠。要规范大小写，请使用 "normcase()"。

   備註:

        在 POSIX 系统上，根据 IEEE Std 1003.1 2013 Edition; 4.13
        Pathname Resolution，如果一个路径名称以两个斜杠开始，则开始字
        符之后的第一个部分将以具体实现所定义的方式来解读，但是超过两个
        开始字符则将被视为单个字符。

     在 3.6 版的變更: 接受一個 *path-like object*。

os.path.realpath(path, *, strict=False)

   返回指定文件的规范路径，消除路径中存在的任何符号链接（如果操作系统
   支持）。

   在默认情况下，对路径的求值将执行至第一个不存在的、导致符号链接循环
   的，或者求值引发 "OSError" 的路径组件。 所有这样的组件将不经修改地
   添加到现有的路径组件。

   会以这种方式来处理的错误包括 "access denied", "not a directory" 或
   "bad argument to internal function"。 因此，结果路径可能不存在或不
   可访问，可能仍然包含链接或循环，并可能遍历至非目录。

   此行为可通过关键字参数来修改：

   如果 *strict* 为 "True"，则在对路径求值时遇到的第一个错误将被重新引
   发。 具体来说，如果 *path* 不存在则会引发 "FileNotFoundError"，或者
   如果因其他原因而不可访问则会引发 "OSError"。

   如果 *strict* 为 "os.path.ALLOW_MISSING"，则 "FileNotFoundError" 以
   外的错误将被重新引发（就像设置 "strict=True" 一样）。 因此，返回的
   路径将不包含任何符号链接，但指定名称的文件及其某些上级目录可能会不
   存在。

   備註:

     这个函数会模拟操作系统生成规范路径的过程，Windows 与 UNIX 的这个
     过程在处理链接和后续路径组成部分的交互方式上有所差异。操作系统
     API 会根据需要来规范化路径，因此通常不需要调用此函数。

   在 3.6 版的變更: 接受一個 *path-like object*。

   在 3.8 版的變更: 在 Windows 上现在可以正确解析符号链接和交接点
   (junction point)。

   在 3.10 版的變更: 新增 *strict* 參數。

   在 3.11.13 版的變更: 增加了用于 *strict* 形参的 "ALLOW_MISSING" 值
   。

os.path.ALLOW_MISSING

   用于 "realpath()" 中 *strict* 参数的特殊值。

   在 3.11.13 版新加入.

os.path.relpath(path, start=os.curdir)

   返回从当前目录或可选的 *start* 目录至 *path* 的相对文件路径。 这只
   是一个路径计算：不会访问文件系统来确认 *path* 或 *start* 是否存在或
   其性质。 在 Windows 上，当 *path* 和 *start* 位于不同驱动器时将引发
   "ValueError"。

   *start* 默认为 "os.curdir"。

   適用：Unix、Windows。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.samefile(path1, path2)

   如果两个路径都指向相同的文件或目录，则返回 "True"。这由设备号和
   inode 号确定，在任一路径上调用 "os.stat()" 失败则抛出异常。

   適用：Unix、Windows。

   在 3.2 版的變更: 新增對 Windows 的支援。

   在 3.4 版的變更: Windows现在使用与其他所有平台相同的实现。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.sameopenfile(fp1, fp2)

   如果文件描述符 *fp1* 和 *fp2* 指向相同文件，则返回 "True"。

   適用：Unix、Windows。

   在 3.2 版的變更: 新增對 Windows 的支援。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.samestat(stat1, stat2)

   如果 stat 元组 *stat1* 和 *stat2* 指向相同文件，则返回 "True"。这些
   stat 元组可能是由 "os.fstat()"、"os.lstat()" 或 "os.stat()" 返回的
   。本函数实现了 "samefile()" 和 "sameopenfile()" 底层所使用的比较过
   程。

   適用：Unix、Windows。

   在 3.4 版的變更: 新增對 Windows 的支援。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.split(path)

   将路径 *path* 拆分为一对，即 "(head, tail)"，其中，*tail* 是路径的
   最后一部分，而 *head* 里是除最后部分外的所有内容。*tail* 部分不会包
   含斜杠，如果 *path* 以斜杠结尾，则 *tail* 将为空。如果 *path* 中没
   有斜杠，*head* 将为空。如果 *path* 为空，则 *head* 和 *tail* 均为空
   。*head* 末尾的斜杠会被去掉，除非它是根目录（即它仅包含一个或多个斜
   杠）。在所有情况下，"join(head, tail)" 指向的位置都与 *path* 相同（
   但字符串可能不同）。另请参见函数 "dirname()" 和 "basename()"。

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.splitdrive(path)

   将路径 *path* 拆分为一对，即 "(drive, tail)"，其中 *drive* 是挂载点
   或空字符串。在没有驱动器概念的系统上，*drive* 将始终为空字符串。在
   所有情况下，"drive + tail" 都与 *path* 相同。

   在 Windows 上，本方法将路径拆分为驱动器/UNC 根节点和相对路径。

   如果路径 path 包含盘符，则 drive 将包含冒号之前的所有内容包括冒号本
   身:

      >>> splitdrive("c:/dir")
      ("c:", "/dir")

   如果路径 path 包含 UNC 路径，则 drive 将包含主机名和 share，直至第
   四个分隔符但不包括该分隔符:

      >>> splitdrive("//host/computer/dir")
      ("//host/computer", "/dir")

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.splitext(path)

   将路径名称 *path* 拆分为 "(root, ext)"  对使得 "root + ext == path"
   ，并且扩展名 *ext* 为空或以句点打头并最多只包含一个句点。

   如果路径 path 不包含扩展名，则 *ext* 将为 "''":

      >>> splitext('bar')
      ('bar', '')

   如果路径 path 包含扩展名，则 *ext* 将被设为该扩展名，包括打头的句点
   。 请注意在其之前的句点将被忽略:

      >>> splitext('foo.bar.exe')
      ('foo.bar', '.exe')
      >>> splitext('/foo/bar.exe')
      ('/foo/bar', '.exe')

   path 中最后一部分如果以点号开头则会被视为 root 的一部分:

      >>> splitext('.cshrc')
      ('.cshrc', '')
      >>> splitext('/foo/....jpg')
      ('/foo/....jpg', '')

   在 3.6 版的變更: 接受一個 *path-like object*。

os.path.supports_unicode_filenames

   如果（在文件系统限制下）允许将任意 Unicode 字符串用作文件名，则为
   "True"。
