pathlib --- 物件導向檔案系統路徑

在 3.4 版被加入.

原始碼:Lib/pathlib/


此模組提供代表檔案系統路徑的類別,能適用不同作業系統的語意。路徑類別分成兩種,一種是純路徑 (pure paths),提供沒有 I/O 的單純計算操作,另一種是實體路徑 (concrete paths),繼承自純路徑但也提供 IO 操作。

顯示 pathlib 中可用類別的繼承圖。 最基礎的類別是 PurePath,它有三個直接子類別: PurePosixPath、PureWindowsPath 和 Path。除了這四個類別之外, 還有兩個類別使用多重繼承: PosixPath 繼承自 PurePosixPath 和 Path,而 WindowsPath 繼承自 PureWindowsPath 和 Path。

如果你之前從未使用過此模組或不確定哪個類別適合你的任務,那你需要的最有可能是 Path。它針對程式執行所在的平台實例化一個實體路徑

純路徑在某些特殊情境下是有用的,例如:

  1. 如果你想在 Unix 機器上處理 Windows 路徑(或反過來),你無法在 Unix 上實例化 WindowsPath,但你可以實例化 PureWindowsPath

  2. 你想確保你的程式在操作路徑的時候不會真的存取到 OS。在這個情況下,實例化其中一種純路徑類別可能是有用的,因為它們不會有任何存取 OS 的操作。

也參考

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'

例外

exception pathlib.UnsupportedOperation

繼承自 NotImplementedError 的例外,當在路徑物件上呼叫不支援的操作時會被引發。

在 3.13 版被加入.

純路徑

純路徑物件提供處理路徑的操作,實際上不會存取檔案系統。有三種方式可以存取這些類別,我們也稱之為類型 (flavours)

class pathlib.PurePath(*pathsegments)

一個通用的類別,表示系統的路徑類型(實例化時會建立一個 PurePosixPathPureWindowsPath):

>>> PurePath('setup.py')      # 執行在 Unix 機器上
PurePosixPath('setup.py')

pathsegments 中的每個元素可以是以下的其中一種:一個表示路徑片段的字串,或一個物件,它實作了 os.PathLike 介面且其中的 __fspath__() 方法會回傳字串,就像是另一個路徑物件:

>>> 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 的一個子類別,該路徑類型表示非 Windows 檔案系統的路徑:

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

pathsegments 的指定方式與 PurePath 類似。

class pathlib.PureWindowsPath(*pathsegments)

PurePath 的一個子類別,該路徑類型表示 Windows 檔案系統的路徑,包括 UNC paths

>>> PureWindowsPath('c:/', 'Users', 'Ximénez')
PureWindowsPath('c:/Users/Ximénez')
>>> PureWindowsPath('//server/share/file')
PureWindowsPath('//server/share/file')

pathsegments 的指定方式與 PurePath 類似。

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

通用屬性

路徑物件是不可變 (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 會得到原始檔案系統路徑的 bytes 物件,就像使用 os.fsencode() 編碼過的一樣:

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

備註

只建議在 Unix 下呼叫 bytes。在 Windows 裡,unicode 形式是檔案系統路徑的權威表示方式。

對個別組成的存取

可以使用下列屬性來存取路徑的個別「組成」(parts, components):

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

用於底層路徑剖析和結合的 os.path 模組的實作:可能是 posixpathntpath

在 3.13 版被加入.

PurePath.drive

若存在則為一個表示磁碟機字母 (drive letter) 或磁碟機名稱 (drive name) 的字串:

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

UNC shares 也被視為磁碟機:

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

若存在則為一個表示(本地或全域)根目錄的字串:

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

UNC shares 都會有一個根目錄:

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

如果路徑以超過兩個連續的斜線開頭,PurePosixPath 會合併它們:

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

備註

此行為符合 The Open Group Base Specifications Issue 6,章節 4.11 路徑名稱解析

「以兩個連續斜線開頭的路徑名稱可以根據實作定義的方式來解讀,儘管如此,開頭超過兩個斜線應該視為單一斜線。」

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

一個不可變的序列,為路徑邏輯上的祖先 (logical ancestors) 提供存取:

>>> 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 版的變更: 父序列現在支援 slices 及負的索引值。

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

備註

這是一個純粹字句上的 (lexical) 運算,因此會有以下行為:

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

如果你想要沿任意的檔案系統路徑往上走,建議要先呼叫 Path.resolve() 來解析符號連結 (symlink) 及去除其中的 ”..”

PurePath.name

最後的路徑組成 (final path component) 的字串表示,不包含任何磁碟機或根目錄:

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

這通常被稱為檔案副檔名。

在 3.14 版的變更: A single dot (".") is considered a valid suffix.

PurePath.suffixes

一個路徑後綴 (suffix) 的串列,通常被稱為檔案副檔名:

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

在 3.14 版的變更: A single dot (".") is considered a valid suffix.

PurePath.stem

最後的路徑組成,不包括後綴:

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

在 3.14 版的變更: A single dot (".") is considered a valid suffix.

PurePath.as_posix()

回傳一個使用正斜線 (/) 的路徑的字串表示:

>>> p = PureWindowsPath('c:\\windows')
>>> str(p)
'c:\\windows'
>>> p.as_posix()
'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

該方法是基於字串的;它既不存取檔案系統,也不特別處理 ".." 片段。以下程式碼是等效的:

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

在 3.9 版被加入.

自從版本 3.12 後不推薦使用,已從版本 3.14 中移除。: 額外引數的傳入已棄用;如果有的話,它們會與 other 連接在一起。

PurePath.is_reserved()

PureWindowsPath 來說,當路徑在 Windows 下被視為保留的話會回傳 True,否則回傳 False。對 PurePosixPath 來說,總是回傳 False

在 3.13 版的變更: Windows 路徑名稱中包含冒號或結尾為點或空格會被視為保留。UNC 路徑可能被視為保留。

自從版本 3.13 後不推薦使用,將會自版本 3.15 中移除。: 此方法已被棄用;請使用 os.path.isreserved() 來檢測 Windows 上的保留路徑。

PurePath.joinpath(*pathsegments)

呼叫此方法會依序結合每個所給定的 pathsegments 到路徑上:

>>> 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.full_match(pattern, *, case_sensitive=None)

將路徑與 glob 形式的模式 (glob-style pattern) 做比對。如果比對成功則回傳 True,否則回傳 False,例如:

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

也參考

模式語言 (pattern language) 文件。

像其它方法一樣,是否區分大小寫會遵循平台的預設行為:

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

case_sensitive 設定成 TrueFalse 會覆蓋這個行為。

在 3.13 版被加入.

PurePath.match(pattern, *, case_sensitive=None)

將路徑與非遞迴 glob 形式的模式 (glob-style pattern) 做比對。如果比對成功則回傳 True,否則回傳