pathlib
--- 物件導向檔案系統路徑¶在 3.4 版被加入.
原始碼:Lib/pathlib/
此模組提供代表檔案系統路徑的類別,能適用不同作業系統的語意。路徑類別分成兩種,一種是純路徑 (pure paths),提供沒有 I/O 的單純計算操作,另一種是實體路徑 (concrete paths),繼承自純路徑但也提供 IO 操作。
如果你之前從未使用過此模組或不確定哪個類別適合你的任務,那你需要的最有可能是 Path
。它針對程式執行所在的平台實例化一個實體路徑。
純路徑在某些特殊情境下是有用的,例如:
如果你想在 Unix 機器上處理 Windows 路徑(或反過來),你無法在 Unix 上實例化 WindowsPath
,但你可以實例化 PureWindowsPath
。
你想確保你的程式在操作路徑的時候不會真的存取到 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'
繼承自 NotImplementedError
的例外,當在路徑物件上呼叫不支援的操作時會被引發。
在 3.13 版被加入.
純路徑物件提供處理路徑的操作,實際上不會存取檔案系統。有三種方式可以存取這些類別,我們也稱之為類型 (flavours):
一個通用的類別,表示系統的路徑類型(實例化時會建立一個 PurePosixPath
或 PureWindowsPath
):
>>> 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
介面的支援。
PurePath
的一個子類別,該路徑類型表示非 Windows 檔案系統的路徑:
>>> PurePosixPath('/etc/hosts')
PurePosixPath('/etc/hosts')
pathsegments 的指定方式與 PurePath
類似。
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):
一個可存取路徑的各組成的元組:
>>> p = PurePath('/usr/bin/python3')
>>> p.parts
('/', 'usr', 'bin', 'python3')
>>> p = PureWindowsPath('c:/Program Files/PSF')
>>> p.parts
('c:\\', 'Program Files', 'PSF')
(特別注意磁碟機跟本地根目錄是如何被重新組合成一個單一組成)
純路徑提供以下方法與屬性:
若存在則為一個表示磁碟機字母 (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'
若存在則為一個表示(本地或全域)根目錄的字串:
>>> 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 路徑名稱解析:
「以兩個連續斜線開頭的路徑名稱可以根據實作定義的方式來解讀,儘管如此,開頭超過兩個斜線應該視為單一斜線。」
磁碟機與根目錄的結合:
>>> PureWindowsPath('c:/Program Files/').anchor
'c:\\'
>>> PureWindowsPath('c:Program Files/').anchor
'c:'
>>> PurePosixPath('/etc').anchor
'/'
>>> PureWindowsPath('//host/share').anchor
'\\\\host\\share\\'
一個不可變的序列,為路徑邏輯上的祖先 (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 及負的索引值。
邏輯上的父路徑:
>>> 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) 及去除其中的 ”..”
。
最後的路徑組成 (final path component) 的字串表示,不包含任何磁碟機或根目錄:
>>> PurePosixPath('my/library/setup.py').name
'setup.py'
UNC 磁碟機名稱並沒有算在內:
>>> PureWindowsPath('//some/share/setup.py').name
'setup.py'
>>> PureWindowsPath('//some/share').name
''
以點分隔路徑的最後一個部分(如存在):
>>> PurePosixPath('my/library/setup.py').suffix
'.py'
>>> PurePosixPath('my/library.tar.gz').suffix
'.gz'
>>> PurePosixPath('my/library').suffix
''
這通常被稱為檔案副檔名。
一個路徑後綴 (suffix) 的串列,通常被稱為檔案副檔名:
>>> PurePosixPath('my/library.tar.gar').suffixes
['.tar', '.gar']
>>> PurePosixPath('my/library.tar.gz').suffixes
['.tar', '.gz']
>>> PurePosixPath('my/library').suffixes
[]
最後的路徑組成,不包括後綴:
>>> PurePosixPath('my/library.tar.gz').stem
'library.tar'
>>> PurePosixPath('my/library.tar').stem
'library'
>>> PurePosixPath('my/library').stem
'library'
回傳一個使用正斜線 (/
) 的路徑的字串表示:
>>> p = PureWindowsPath('c:\\windows')
>>> str(p)
'c:\\windows'
>>> p.as_posix()
'c:/windows'
回傳一個路徑是否是絕對路徑。一個路徑被視為絕對路徑的條件是它同時有根目錄及(如果該系統類型允許的話)磁碟機:
>>> 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
回傳此路徑是否為 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 版被加入.
Deprecated since version 3.12, will be removed in version 3.14: 額外引數的傳入已棄用;如果有的話,它們會與 other 連接在一起。
對 PureWindowsPath
來說,當路徑在 Windows 下被視為保留的話會回傳 True
,否則回傳 False
。對 PurePosixPath
來說,總是回傳 False
。
在 3.13 版的變更: Windows 路徑名稱中包含冒號或結尾為點或空格會被視為保留。UNC 路徑可能被視為保留。
Deprecated since version 3.13, will be removed in version 3.15: 此方法已被棄用;請使用 os.path.isreserved()
來檢測 Windows 上的保留路徑。
呼叫此方法會依序結合每個所給定的 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')
將路徑與 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
也參考
像其它方法一樣,是否區分大小寫會遵循平台的預設行為:
>>> PurePosixPath('b.py').full_match('*.PY')
False
>>> PureWindowsPath('b.py').full_match('*.PY')
True
將 case_sensitive 設定成 True
或 False
會覆蓋這個行為。
在 3.13 版被加入.
將路徑與非遞迴 glob 形式的模式 (glob-style pattern) 做比對。如果比對成功則回傳 True
,否則回傳 False
。
此方法類似於 full_match()
,但不允許空白模式(會引發 ValueError
)、不支援遞迴萬用字元 "**
"(它會像非遞迴的 "*
" 一樣),且如果提供相對模式,則會從右邊進行比對:
>>> 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
在 3.12 版的變更: pattern 參數接受類路徑物件。
在 3.12 版的變更: 新增 case_sensitive 參數。
計算這個路徑相對於 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 941, in relative_to
raise ValueError(error_message.format(str(self), str(formatted)))
ValueError: '/etc/passwd' is not in the subpath of '/usr' OR one path is relative and the other is absolute.
當 walk_up 是 False(預設值),路徑必須以 other 為開始。當此引數是 True,可能會加入 ..
以組成相對路徑。在其他情況下,例如路徑參考到不同的磁碟機,則會引發 ValueError
:
>>> p.relative_to('/usr', walk_up=True)
PurePosixPath('../etc/passwd')
>>> p.relative_to('foo', walk_up=True)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pathlib.py", line 941, in relative_to
raise ValueError(error_message.format(str(self), str(formatted)))
ValueError: '/etc/passwd' is not on the same drive as 'foo' OR one path is relative and the other is absolute.
警告
這個函式是 PurePath
的一部分且可以在字串上運作。它不會檢查或存取實際的檔案架構。這會影響到 walk_up 選項,因為它假設路徑中沒有符號連結;如果需要解析符號連結的話可以先呼叫 resolve()
。
在 3.12 版的變更: 加入 walk_up 參數(舊的行為和 walk_up=False
相同)。
Deprecated since version 3.12, will be removed in version 3.14: 額外位置引數的傳入已棄用;如果有的話,它們會與 other 連接在一起。
回傳一個修改 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
回傳一個修改 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 版被加入.
回傳一個修改 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')
透過結合給定的 pathsegments 建立一個相同型別的新路徑物件,當一個衍生路徑被建立的時候會呼叫這個方法,例如從 parent
和 relative_to()
建立衍生路徑。子類別可以覆寫此方法來傳遞資訊給衍生路徑,例如:
from pathlib import PurePosixPath
class MyPath(PurePosixPath):
def __init__(self, *pathsegments, session_id):
super().__init__(*pathsegments)
self.session_id = session_id
def with_segments(self, *pathsegments):
return type(self)(*pathsegments, session_id=self.session_id)
etc = MyPath('/etc', session_id=42)
hosts = etc / 'hosts'
print(hosts.session_id) # 42
在 3.12 版被加入.
實體路徑是純路徑類別的子類別。除了後者本來就有提供的操作,它們也提供方法可以對路徑物件做系統呼叫。有三種方式可以實例化實體路徑:
PurePath
的子類別,此類別表示系統的路徑類型的實體路徑(實例化時會建立一個 PosixPath
或 WindowsPath
):
>>> Path('setup.py')
PosixPath('setup.py')
pathsegments 的指定方式與 PurePath
類似。
Path
和 PurePosixPath
的子類別,此類別表示實體非 Windows 檔案系統路徑:
>>> PosixPath('/etc/hosts')
PosixPath('/etc/hosts')
pathsegments 的指定方式與 PurePath
類似。
在 3.13 版的變更: 在 Windows 上會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
Path
和 PureWindowsPath
的子類別,此類別表示實體 Windows 檔案系統路徑:
>>> WindowsPath('c:/', 'Users', 'Ximénez')
WindowsPath('c:/Users/Ximénez')
pathsegments 的指定方式與 PurePath
類似。
在 3.13 版的變更: 在非 Windows 平台上會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
你只能實例化對應你的系統的類別類型(允許在不相容的路徑類型上做系統呼叫可能在你的應用程式導致漏洞或故障):
>>> 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__,))
UnsupportedOperation: cannot instantiate 'WindowsPath' on your system
有些實體路徑方法會在系統呼叫失敗(例如因為路徑不存在)時引發 OSError
。
實體路徑物件可以從符合 RFC 8089 中的 'file' URI 建立,也可以以該形式來表示。
備註
檔案 URI 在跨不同檔案系統編碼的機器上是無法移植的。
從剖析 'file' URI 回傳新的路徑物件。例如:
>>> p = Path.from_uri('file:///etc/hosts')
PosixPath('/etc/hosts')
在 Windows 上,從 URI 可以剖析 DOS 裝置和 UNC 路徑:
>>> p = Path.from_uri('file:///c:/windows')
WindowsPath('c:/windows')
>>> p = Path.from_uri('file://server/share')
WindowsPath('//server/share')
支援多種變形:
>>> p = Path.from_uri('file:////server/share')
WindowsPath('//server/share')
>>> p = Path.from_uri('file://///server/share')
WindowsPath('//server/share')
>>> p = Path.from_uri('file:c:/windows')
WindowsPath('c:/windows')
>>> p = Path.from_uri('file:/c|/windows')
WindowsPath('c:/windows')
如果 URI 不是 file:
開頭,或是剖析後的路徑不是絕對路徑,則會引發 ValueError
。
在 3.13 版被加入.
以 'file' URI 來表示路徑。如果路徑不是絕對的則會引發 ValueError
。
>>> p = PosixPath('/etc/passwd')
>>> p.as_uri()
'file:///etc/passwd'
>>> p = WindowsPath('c:/Windows')
>>> p.as_uri()
'file:///c:/Windows'
因為歷史上的原因,此方法也可以從 PurePath
物件上使用。然而,它使用 os.fsencode()
而讓它完全不純粹。
回傳一個代表使用者家目錄的新的路徑物件(像以 ~
構成的 os.path.expanduser()
的回傳一樣)。如果無法解析家目錄,會引發 RuntimeError
。
>>> Path.home()
PosixPath('/home/antoine')
在 3.5 版被加入.
回傳一個展開 ~
和 ~user
構成的新路徑,像 os.path.expanduser()
回傳的一樣。如果無法解析家目錄,會引發 RuntimeError
。
>>> p = PosixPath('~/films/Monty Python')
>>> p.expanduser()
PosixPath('/home/eric/films/Monty Python')
在 3.5 版被加入.
回傳一個代表目前目錄的新的路徑物件(像 os.getcwd()
回傳的一樣):
>>> Path.cwd()
PosixPath('/home/antoine/pathlib')
將路徑轉換為絕對路徑,不進行標準化或解析符號連結。回傳一個新的路徑物件:
>>> p = Path('tests')
>>> p
PosixPath('tests')
>>> p.absolute()
PosixPath('/home/antoine/pathlib/tests')
將路徑轉換為絕對路徑,解析所有符號連結。回傳一個新的路徑物件:
>>> 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
,則引發 OSError
。如果 strict 為 False
,則將盡可能解析該路徑,並將任何剩餘部分追加到路徑中,而不檢查其是否存在。
在 3.6 版的變更: 新增 strict 參數(在 3.6 版本之前的行為是嚴格的)。
在 3.13 版的變更: 在嚴格模式下,符號連結迴圈會像其他錯誤一樣來處理:OSError
會被引發,而在非嚴格模式下,不會引發任何例外。在先前版本中,不管 strict 的值是什麼,都會引發 RuntimeError
。
回傳符號連結指向的路徑(如 os.readlink()
的回傳值):
>>> p = Path('mylink')
>>> p.symlink_to('setup.py')
>>> p.readlink()
PosixPath('setup.py')
在 3.9 版被加入.
在 3.13 版的變更: 如果 os.readlink()
不可用,會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
在 3.8 版的變更: exists()
、is_dir()
、is_file()
、is_mount()
、is_symlink()
、is_block_device()
、is_char_device()
、is_fifo()
、is_socket()
遇到路徑包含 OS 層無法表示的字元時現在會回傳 False
而不是引發例外。
回傳一個包含該路徑資訊的 os.stat_result
物件,像 os.stat()
一樣。每次呼叫此方法都會重新查詢結果。
此方法通常會跟隨 (follow) 符號連結;想要取得符號連結的資訊,可以加上引數 follow_symlinks=False
或使用 lstat()
。
>>> p = Path('setup.py')
>>> p.stat().st_size
956
>>> p.stat().st_mtime
1327883547.852554
在 3.10 版的變更: 新增 follow_symlinks 參數。
類似 Path.stat()
,但如果該路徑指向一個符號連結,則回傳符號連結的資訊而不是其指向的目標。
如果路徑指向存在的檔案或目錄則回傳 True
。
此方法通常會跟隨符號連結;如果想檢查符號連結是否存在,可以加上引數 follow_symlinks=False
。
>>> Path('.').exists()
True
>>> Path('setup.py').exists()
True
>>> Path('/etc').exists()
True
>>> Path('nonexistentfile').exists()
False
在 3.12 版的變更: 新增 follow_symlinks 參數。
如果該路徑指向一個普通檔案則回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
此方法通常會跟隨符號連結;如果想將符號連結除外,可以加上引數 follow_symlinks=False
。
在 3.13 版的變更: 新增 follow_symlinks 參數。
如果該路徑指向一個目錄則回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
此方法通常會跟隨符號連結;如果想將對目錄的符號連結除外,可以加上引數 follow_symlinks=False
。
在 3.13 版的變更: 新增 follow_symlinks 參數。
如果該路徑指向一個符號連結則回傳 True
,否則回傳 False
。
如果該路徑不存在也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
如果該路徑指向一個連接點 (junction) 則回傳 True
,對其他類型的檔案則回傳 False
。目前只有 Windows 支援連接點。
在 3.12 版被加入.
如果路徑是一個 mount point(一個檔案系統裡掛載不同檔案系統的存取點)則回傳 True
。在 POSIX 上,此函式檢查 path 的父路徑 path/..
是否和 path 在不同的裝置上,或者 path/..
和 path 是否指向相同裝置的相同 i-node ── 這對於所有 Unix 和 POSIX 變體來說應該會偵測出掛載點。在 Windows 上,一個掛載點被視為一個根磁碟機字母(例如 c:\
)、一個 UNC share(例如 \\server\share
)或是掛載的檔案系統目錄。
在 3.7 版被加入.
在 3.12 版的變更: 加入對 Windows 的支援。
如果該路徑指向一個 Unix socket(或者是一個指向 Unix socket 的符號連結)則會回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
如果該路徑指向一個 FIFO(或者是一個指向 FIFO 的符號連結)則會回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
如果該路徑指向一個區塊裝置 (block device)(或者是一個指向區塊裝置的符號連結)則會回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
如果該路徑指向一個字元裝置 (character device)(或者是一個指向字元裝置的符號連結)則會回傳 True
,如果指向其他類型的檔案則回傳 False
。
如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False
;其他錯誤(例如權限錯誤)則會傳遞出來。
回傳此路徑是否指向與 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 版被加入.
開啟該路徑指向的檔案,像內建的 open()
函式做的一樣:
>>> p = Path('setup.py')
>>> with p.open() as f:
... f.readline()
...
'#!/usr/bin/env python3\n'
將路徑指向的檔案的解碼內容以字串形式回傳:
>>> p = Path('my_text_file')
>>> p.write_text('Text file contents')
18
>>> p.read_text()
'Text file contents'
該檔案被打開並且隨後關閉。可選參數的含義與 open()
中的相同。
在 3.5 版被加入.
在 3.13 版的變更: 新增 newline 參數。
將路徑指向的檔案的二進位內容以一個位元組物件回傳:
>>> p = Path('my_binary_file')
>>> p.write_bytes(b'Binary file contents')
20
>>> p.read_bytes()
b'Binary file contents'
在 3.5 版被加入.
以文字模式開啟指向的檔案,將 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 參數。
以位元組模式開啟指向的檔案,將 data 寫到檔案,並關閉檔案:: :
>>> p = Path('my_binary_file')
>>> p.write_bytes(b'Binary file contents')
20
>>> p.read_bytes()
b'Binary file contents'
一個名稱相同的已存在檔案會被覆寫。
在 3.5 版被加入.
當該路徑指向一個目錄,會 yield 目錄裡面的路徑物件:
>>> 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')
子路徑會以任意順序被 yield,且不會包含特殊項目 '.'
和 '..'
。如果一個檔案在建立這個疊代器之後加到該目錄或從目錄刪除,這個檔案的路徑物件是否會被包含是沒有明定的。
如果路徑不是目錄或無法存取,則會引發 OSError
。
在該路徑表示的目錄裡,以 glob 方式比對所給定的相對 pattern,並 yield 所有比對到的檔案(任意類型):
>>> sorted(Path('.').glob('*.py'))
[PosixPath('pathlib.py'), PosixPath('setup.py'), PosixPath('test_pathlib.py')]
>>> sorted(Path('.').glob('*/*.py'))
[PosixPath('docs/conf.py')]
>>> sorted(Path('.').glob('**/*.py'))
[PosixPath('build/lib/pathlib.py'),
PosixPath('docs/conf.py'),
PosixPath('pathlib.py'),
PosixPath('setup.py'),
PosixPath('test_pathlib.py')]
也參考
預設情況下,或者當 case_sensitive 僅限關鍵字引數被設定為 None
的時候,此方法會使用平台特定的大小寫規則來比對路徑;通常在 POSIX 上會區分大小寫,而在 Windows 上不區分大小寫。將 case_sensitive 設成 True
或 False
會覆寫這個行為。
預設情況下,或者當 recurse_symlinks 僅限關鍵字引數被設定為 False
的時候,此方法會跟隨符號連結,除非在擴展 "**
" 萬用字元時。將 recurse_symlinks 設成 True
以總是跟隨符號連結。
引發一個附帶引數 self
、pattern
的稽核事件 pathlib.Path.glob
。
在 3.12 版的變更: 新增 case_sensitive 參數。
在 3.13 版的變更: 新增 recurse_symlinks 參數。
在 3.13 版的變更: pattern 參數接受類路徑物件。
在 3.13 版的變更: 從掃描檔案系統引發的任何 OSError
例外都會被抑制。在先前版本中,在許多情況下這種例外都會被抑制,但不是所有情況。
遞迴地 glob 給定的相對 pattern。這相當於在給定的相對 pattern 前面加上 "**/
" 並呼叫 Path.glob()
。
也參考
引發一個附帶引數 self
、pattern
的稽核事件 pathlib.Path.rglob
。
在 3.12 版的變更: 新增 case_sensitive 參數。
在 3.13 版的變更: 新增 recurse_symlinks 參數。
在 3.13 版的變更: pattern 參數接受類路徑物件。
透過由上而下或由下而上地走訪目錄樹產生目錄樹裡的檔案名稱。
對每個以 self 為根且在目錄樹裡的目錄(包含 self 但不包含 '.' 和 '..' ),此方法會 yield 一個 (dirpath, dirnames, filenames)
的三元素元組。
dirpath 是一個目前走訪到的目錄的 Path
,dirnames 是一個 dirpath 裡的子目錄名稱的字串串列(不包含 '.'
和 '..'
),而 filenames 是一個 dirpath 裡非目錄檔案名稱的字串串列。要取得在 dirpath 裡檔案或目錄的完整路徑(以 self 開頭),可以使用 dirpath / name
。會根據檔案系統來決定串列是否有排序。
如果可選引數 top_down 是 true(預設值),一個目錄的三元素元組會在其任何子目錄的三元素元組之前產生(目錄是由上而下走訪)。如果 top_down 是 false,一個目錄的三元素元組會在其所有子目錄的三元素元組之後產生(目錄是由下而上走訪)。不論 top_down 的值是什麼,子目錄的串列會在走訪該目錄及其子目錄的三元素元組之前取得。
當 top_down 是 true,呼叫者可以原地 (in-place) 修改 dirnames 串列(例如使用 del
或切片賦值 (slice assignment)),且 Path.walk()
只會遞迴進名稱依然留在 dirnames 裡的子目錄。這可以用來修剪搜尋,或者強加特定順序的瀏覽,或者甚至在繼續 Path.walk()
之前,用來告訴 Path.walk()
關於呼叫者建立或重新命名的目錄。當 top_down 是 false 的時候,修改 dirnames 對 Path.walk()
的行為沒有影響,因為 dirnames 裡的目錄已經在 dirnames yield 給呼叫者之前被產生。
預設來自 os.scandir()
的錯誤會被忽略。如果指定了可選引數 on_error(它應該要是一個可呼叫物件),它會被以一個 OSError
實例為引數來呼叫。這個可呼叫物件可以處理錯誤以繼續走訪,或者再次引發錯誤來停止走訪。注意,檔案名稱可以從例外物件的 filename
屬性來取得。
預設 Path.walk()
不會跟隨符號連結,而是會把它們加到 filenames 串列。將 follow_symlinks 設定為 true 會解析符號連結,並將它們根據其指向的目標放在適當的 dirnames 和 filenames,而因此瀏覽到符號連結指向的目錄(在有支援符號連結的地方)。
備註
需要注意的是如果符號連結指向一個其本身的父目錄,則將 follow_symlinks 設定為 true 會導致無窮的遞迴。Path.walk()
不會紀錄其已經瀏覽過的目錄。
備註
Path.walk()
假設其走訪的目錄在執行過程中不會被修改。舉例來說,如果在 dirnames 裡的目錄已經被一個符號連結取代,且 follow_symlinks 是 false,Path.walk()
依然會試著往下進入它。為了防止這樣的行為,可以從 dirnames 適當地移除目錄。
備註
如果 follow_symlinks 是 false,和 os.walk()
行為不同的是 Path.walk()
會將指向目錄的符號連結放在 filenames 串列。
這個範例會顯示在每個目錄裡所有檔案使用的位元組數量,同時間忽略 __pycache__
目錄:
from pathlib import Path
for root, dirs, files in Path("cpython/Lib/concurrent").walk(on_error=print):
print(
root,
"consumes",
sum((root / file).stat().st_size for file in files),
"bytes in",
len(files),
"non-directory files"
)
if '__pycache__' in dirs:
dirs.remove('__pycache__')
下一個範例是 shutil.rmtree()
的一個簡單的實作方式。由下而上走訪目錄樹是必要的,因為 rmdir()
不允許在目錄為空之前刪除它:
# 刪除可從 "top" 目錄到達的所有東西。
# 注意:這是危險的!例如,如果 top == Path('/'),
# 它可能會刪除你所有的檔案。
for root, dirs, files in top.walk(top_down=False):
for name in files:
(root / name).unlink()
for name in dirs:
(root / name).rmdir()
在 3.12 版被加入.
根據給定路徑來建立一個檔案。如果 mode 有給定,它會與行程的 umask
值結合,以確定檔案模式和存取旗標。當檔案已經存在時,若 exist_ok 為 true 則函式不會失敗(其變更時間會被更新為當下時間),否則會引發 FileExistsError
。
也參考
open()
、write_text()
和 write_bytes()
方法通常用於建立檔案。
在給定路徑下建立一個新的目錄。如果有給 mode 則會結合行程 (process) 的 umask
值來決定檔案模式與存取旗標 (access flag)。如果路徑已經存在,會引發 FileExistsError
。
如果 parents 是 true,則任何缺少的父路徑都會依需要被建立;它們不考慮 mode 而會以預設的權限來建立(模仿 POSIX 的 mkdir -p
指令)。
如果 parents 是 false(預設值),缺少的父路徑會引發 FileNotFoundError
。
如果 exist_ok 是 false(預設值),則當目標目錄已經存在的話會引發 FileExistsError
。
如果 exist_ok 是 true,只有當最後的路徑組成不是一個已存在的非目錄檔案,FileExistsError
例外會被忽略(與 POSIX 的 mkdir -p
指令行為相同)。
在 3.5 版的變更: 新增 exist_ok 參數。
使這個路徑成為一個指向 target 的符號連結。
在 Windows 上,符號連結代表一個檔案或目錄,且不會隨著目標 (target) 動態改變。如果目標存在,則符號連結的類型會被建立來符合其目標。否則如果 target_is_directory 是 true,該符號連結會被建立成目錄,如果不是則建立成檔案(預設值)。在非 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()
相反。
在 3.13 版的變更: 如果 os.symlink()
不可用,會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
使這個路徑成為與 target 相同檔案的一個硬連結 (hard link)。
備註
引數的順序 (link, target) 和 os.link()
相反。
在 3.10 版被加入.
在 3.13 版的變更: 如果 os.link()
不可用,會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
將此檔案或目錄重新命名為給定的 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'
目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於目前的工作目錄進行解釋,而不是相對於 Path
物件所在的目錄。
此功能是使用 os.rename()
實現的,並提供相同的保證。
在 3.8 版的變更: 新增了回傳值,回傳新的 Path
實例。
將此檔案或目錄重新命名為給定的 target,並回傳一個指向 target 的新 Path
實例。如果 target 指向一個現有的檔案或空目錄,它將被無條件地取代。
目標路徑可以是絕對路徑或相對路徑。相對路徑會相對於目前的工作目錄進行解釋,而不是相對於 Path
物件所在的目錄。
在 3.8 版的變更: 新增了回傳值,回傳新的 Path
實例。
移除這個檔案或符號連結。如果路徑指向目錄,請改用 Path.rmdir()
。
如果 missing_ok 是 false(預設值),FileNotFoundError
會在路徑不存在時被引發。
如果 missing_ok 是 true,FileNotFoundError
例外會被忽略(行為與 POSIX rm -f
指令相同)。
在 3.8 版的變更: 新增 missing_ok 參數。
移除此目錄。該目錄必須為空。
回傳擁有該檔案的用戶名稱。如果在系統資料庫中找不到該檔案的使用者識別字 (UID),則會引發 KeyError
。
此方法通常會跟隨符號連結;如果想取得符號連結的擁有者,可以加上引數 follow_symlinks=False
。
在 3.13 版的變更: 如果 pwd
模組不可用,會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
在 3.13 版的變更: 新增 follow_symlinks 參數。
回傳擁有該檔案的群組名稱。如果在系統資料庫裡找不到檔案的群組識別字 (GID) 會引發 KeyError
。
此方法通常會跟隨符號連結;如果想取得符號連結的群組,可以加上引數 follow_symlinks=False
。
在 3.13 版的變更: 如果 grp
模組不可用,會引發 UnsupportedOperation
。在先前版本中,則是引發 NotImplementedError
。
在 3.13 版的變更: 新增 follow_symlinks 參數。
修改檔案模式 (file mode) 與權限,像 os.chmod()
一樣。
此方法通常會跟隨符號連結。一些 Unix 類型支援修改符號連結本身的權限;在這些平台上你可以加上引數 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.chmod()
,但如果該路徑指向一個符號連結,則符號連結的模式 (mode) 會被改變而不是其指向的目標。
以下的萬用字元在 full_match()
、glob()
和 rglob()
的模式中被支援:
**
(整個片段)匹配任何數量的檔案或目錄片段,包括零個。
*
(整個片段)匹配一個檔案或目錄的片段。
*
(片段的一部分)匹配任意數量的非分隔字元,包括零個。
?
匹配一個非分隔字元。
[seq]
Matches one character in seq, where seq is a sequence of characters.
Range expressions are supported; for example, [a-z]
matches any lowercase ASCII letter.
Multiple ranges can be combined: [a-zA-Z0-9_]
matches any ASCII letter, digit, or underscore.
[!seq]
Matches one character not in seq, where seq follows the same rules as above.
對於文本 (literal) 匹配,可以用方括號包裝元字元 (meta-characters)。例如,"[?]"
會匹配字元 "?"
。
"**
" 萬用字元讓它可以做遞迴 glob。例如:
模式 |
意涵 |
---|---|
" |
至少有一個片段的路徑。 |
" |
最後一個片段以 " |
" |
任何以 " |
" |
任何以 " |
備註
Glob 使用 **
萬用字元會訪問目錄樹中的每個目錄。對於大型的目錄樹,搜尋可能需要花費很長的時間。
在 3.13 版的變更: Glob 使用結尾為 **
的模式會同時回傳檔案和目錄。在先前版本中,只會回傳目錄。
在 Path.glob()
和 rglob()
中,可以在模式後面加上斜線以只匹配目錄。
glob
模組的比較¶Path.glob()
和 Path.rglob()
接受的模式和產生的結果與 glob
模組略有不同:
pathlib 中以點開頭的檔案並不特別。這和將 include_hidden=True
傳遞給 glob.glob()
相同。
**
模式組成在 pathlib 中總是遞迴的。這與將 recursive=True
傳遞給 glob.glob()
相同。
在 pathlib 中,**
模式組成預設不跟隨符號連結。這在 glob.glob()
中沒有等效的行為,但你可以將 recurse_symlinks=True
傳遞給 Path.glob()
以獲得相容的行為。
與所有 PurePath
和 Path
物件一樣,從 Path.glob()
和 Path.rglob()
回傳的值不包含結尾斜線。
pathlib 的 path.glob()
和 path.rglob()
回傳的值包含了 path 作為前綴,而 glob.glob(root_dir=path)
的結果則不會如此。
pathlib 的 path.glob()
和 path.rglob()
回傳的值可能包含 path 本身,例如當使用 "**
" 做 glob 的時候,然而 glob.glob(root_dir=path)
的結果則永遠不會包含一個對應到 path 的空字串。
os
和 os.path
模組的比較¶pathlib 使用 PurePath
和 Path
物件來實作路徑操作,因此它被稱為是物件導向的。另一方面,os
和 os.path
模組提供能夠與底層 str
和 bytes
物件互動的函式,這是一種更程序式的方法。有些使用者認為物件導向的風格更易讀。
os
和 os.path
中的許多函式支援 bytes
路徑和相對路徑的目錄描述器 (paths relative to directory descriptors)。這些功能在 pathlib 中不可用。
Python 的 str
和 bytes
型別,以及 os
和 os.path
模組的一些部分,是用 C 寫的且非常快速。pathlib 是用純 Python 寫的且通常比較慢,但很少會慢到足以產生影響。
pathlib 的路徑正規化略比 os.path
更武斷和一致。例如,儘管 os.path.abspath()
會從路徑中移除 "..
" 片段,如果包含符號連結的話這可能會改變其意義,而 Path.absolute()
則會保留這些片段以增加安全性。
pathlib 的路徑正規化可能會使它不適合某些應用程式:
pathlib 將 Path("my_folder/")
正規化為 Path("my_folder")
,這會在提供給各種操作系統 API 和命令列工具時改變路徑的意義。具體來說,缺少結尾分隔符號可能會允許該路徑被解析為檔案或目錄,而不只是目錄。
pathlib 將 Path("./my_program")
正規化為 Path("my_program")
,這會在作為執行檔搜尋路徑使用時改變路徑的意義,例如在 shell 或在衍生 (spawn) 子行程時。具體來說,在路徑中缺少分隔符號可能會使其強制在 PATH
中尋找,而不是目前目錄。
因為這些差異,pathlib 不是 os.path
的直接替代品。
以下是一張表格,對應許多 os
函式及其相符於 PurePath
/Path
的項目。
註腳