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

在 3.4 版被加入.

原始碼:Lib/pathlib.py


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

Inheritance diagram showing the classes available in pathlib. The most basic class is PurePath, which has three direct subclasses: PurePosixPath, PureWindowsPath, and Path. Further to these four classes, there are two classes that use multiple inheritance: PosixPath subclasses PurePosixPath and Path, and WindowsPath subclasses PureWindowsPath and 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'

純路徑

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

class pathlib.PurePath(*pathsegments)

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

>>> PurePath('setup.py')      # Running on a Unix machine
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.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
''
PurePath.suffixes

路徑檔案副檔名的串列:

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

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

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

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

>>> 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 連接在一起。

PurePath.is_reserved()

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

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

在保留路徑上的檔案系統呼叫會神秘地失敗或有意外的效果。

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

將路徑與 glob 形式的樣式 (glob-style pattern) 做比對。如果比對成功則回傳 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

pattern 可以是另一個路徑物件;這會加速對多個檔案比對相同的樣式:

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

備註

The recursive wildcard "**" isn't supported by this method (it acts like non-recursive "*".)

在 3.12 版的變更: 接受一個有實作 os.PathLike 介面的物件。

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

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

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

在 3.12 版的變更: 新增 case_sensitive 參數。

PurePath.relative_to(other, walk_up=False)

計算這個路徑相對於 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 連接在一起。

PurePath.with_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')
PurePath.with_segments(*pathsegments)

透過結合給定的 pathsegments 建立一個相同類型的新路徑物件,當一個衍生路徑被建立的時候會呼叫這個方法,例如從 parentrelative_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 版被加入.

實體路徑

實體路徑是純路徑類別的子類別。除了後者本來就有提供的操作,它們也提供方法可以對路徑物件做系統呼叫。有三種方式可以實例化實體路徑:

class pathlib.Path(*pathsegments)

PurePath 的子類別,此類別表示系統的路徑類型的實體路徑(實例化時會建立一個 PosixPathWindowsPath):

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

pathsegments 的指定方式與 PurePath 類似。

class pathlib.PosixPath(*pathsegments)

PathPurePosixPath 的子類別,此類別表示實體非 Windows 檔案系統路徑:

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

pathsegments 的指定方式與 PurePath 類似。

class pathlib.WindowsPath(*pathsegments)

PathPureWindowsPath 的子類別,此類別表示實體 Windows 檔案系統路徑:

>>> WindowsPath('c:/', 'Users', 'Ximénez')
WindowsPath('c:/Users/Ximénez')

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

Expanding and resolving paths

classmethod Path.home()

回傳一個代表使用者家目錄的新的路徑物件(像以 ~ 構成的 os.path.expanduser() 的回傳一樣)。如果無法解析家目錄,會引發 RuntimeError

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

在 3.5 版被加入.

Path.expanduser()

回傳一個展開 ~~user 構成的新路徑,像 os.path.expanduser() 回傳的一樣。如果無法解析家目錄,會引發 RuntimeError

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

在 3.5 版被加入.

classmethod Path.cwd()

回傳一個代表目前目錄的新的路徑物件(像 os.getcwd() 回傳的一樣):

>>> Path.cwd()
PosixPath('/home/antoine/pathlib')
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')

如果路徑不存在且 strictTrue,則引發 FileNotFoundError。如果 strictFalse,則將盡可能解析該路徑,並將任何剩餘部分追加到路徑中,而不檢查其是否存在。如果在解析過程中遇到無窮迴圈,則引發 RuntimeError

在 3.6 版的變更: 新增 strict 參數(在 3.6 版本之前的行為是嚴格的)。

回傳符號連結指向的路徑(如 os.readlink() 的回傳值):

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

在 3.9 版被加入.

Querying file type and status

在 3.8 版的變更: exists()is_dir()is_file()is_mount()is_symlink()is_block_device()is_char_device()is_fifo()is_socket() 遇到路徑包含 OS 層無法表示的字元時現在會回傳 False 而不是引發例外。

Path.stat(*, follow_symlinks=True)

回傳一個包含該路徑資訊的 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.lstat()

類似 Path.stat(),但如果該路徑指向一個符號連結,則回傳符號連結的資訊而不是其指向的目標。

Path.exists(*, follow_symlinks=True)

如果路徑指向存在的檔案或目錄則回傳 True

此方法通常會跟隨符號連結;如果想檢查符號連結是否存在,可以加上引數 follow_symlinks=False

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

在 3.12 版的變更: 新增 follow_symlinks 參數。

Path.is_file()

如果該路徑指向一個普通檔案(或者是一個指向普通檔案的符號連結)則回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

Path.is_dir()

如果該路徑指向一個目錄(或者是一個指向目錄的符號連結)則回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

如果該路徑指向一個符號連結則回傳 True,否則回傳 False

如果該路徑不存在也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

Path.is_junction()

如果該路徑指向一個連接點 (junction) 則回傳 True,對其他類型的檔案則回傳 False。目前只有 Windows 支援連接點。

在 3.12 版被加入.

Path.is_mount()

如果路徑是一個 mount point(一個檔案系統裡掛載不同檔案系統的存取點)則回傳 True。在 POSIX 上,此函式檢查 path 的父路徑 path/.. 是否和 path 在不同的裝置上,或者 path/..path 是否指向相同裝置的相同 i-node ── 這對於所有 Unix 和 POSIX 變體來說應該會偵測出掛載點。在 Windows 上,一個掛載點被視為一個根磁碟機字母(例如 c:\)、一個 UNC share(例如 \\server\share)或是掛載的檔案系統目錄。

在 3.7 版被加入.

在 3.12 版的變更: 加入對 Windows 的支援。

Path.is_socket()

如果該路徑指向一個 Unix socket(或者是一個指向 Unix socket 的符號連結)則會回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

Path.is_fifo()

如果該路徑指向一個 FIFO(或者是一個指向 FIFO 的符號連結)則會回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

Path.is_block_device()

如果該路徑指向一個區塊裝置 (block device)(或者是一個指向區塊裝置的符號連結)則會回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

Path.is_char_device()

如果該路徑指向一個字元裝置 (character device)(或者是一個指向字元裝置的符號連結)則會回傳 True,如果指向其他類型的檔案則回傳 False

如果路徑不存在或者是一個斷掉的符號連結則也會回傳 False;其他錯誤(例如權限錯誤)則會傳遞出來。

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 版被加入.

Reading and writing files

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.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.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.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 參數。

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

當該路徑指向一個目錄,會 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,且不會包含特殊項目 '.''..'。如果一個檔案在建立這個疊代器之後加到該目錄或從目錄刪除,這個檔案的路徑物件是否會被包含是沒有明定的。

If the path is not a directory or otherwise inaccessible, OSError is raised.

Path.glob(pattern, *, case_sensitive=None)

在該路徑表示的目錄裡,以 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')]

模式 (pattern) 和給 fnmatch 的一樣,加上 "**" 代表「目前目錄及所有遞迴的子目錄」。也就是說它能夠做遞迴的 glob 比對:

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

此方法在頂層目錄上呼叫 Path.is_dir() 並傳遞引發的任何 OSError 例外。將會抑制在目錄對於 OSError 例外的後續掃描。

預設情況下,或者當 case_sensitive 僅限關鍵字引數被設定為 None 的時候,此方法會使用平台特定的大小寫規則來比對路徑;通常在 POSIX 上會區分大小寫,而在 Windows 上不區分大小寫。將 case_sensitive 設成 TrueFalse 會覆寫這個行為。

備註

在很大的目錄樹裡使用 "**" 可能會耗費過多的時間。

引發一個附帶引數 selfpattern稽核事件 pathlib.Path.glob

在 3.11 版的變更: 如果 pattern 以路徑名稱組成的分隔符號(sepaltsep)作結尾則只會回傳目錄。

在 3.12 版的變更: 新增 case_sensitive 參數。

Path.rglob(pattern, *, case_sensitive=None)

遞迴地 glob 給定的相對 pattern。這相當於在給定的相對 pattern 前面加上 "**/" 並呼叫 Path.glob(),其中 patterns 和給 fnmatch 的相同:

>>> sorted(Path().rglob("*.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 設成 TrueFalse 會覆寫這個行為。

引發一個附帶引數 selfpattern稽核事件 pathlib.Path.rglob

在 3.11 版的變更: 如果 pattern 以路徑名稱組成的分隔符號(sepaltsep)作結尾則只會回傳目錄。

在 3.12 版的變更: 新增 case_sensitive 參數。

Path.walk(top_down=True, on_error=None, follow_symlinks=False)

透過由上而下或由下而上地走訪目錄樹產生目錄樹裡的檔案名稱。

對每個以 self 為根且在目錄樹裡的目錄(包含 self 但不包含 '.' 和 '..' ),此方法會 yield 一個 (dirpath, dirnames, filenames) 的三元素元組。

dirpath 是一個目前走訪到的目錄的 Pathdirnames 是一個 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 的時候,修改 dirnamesPath.walk() 的行為沒有影響,因為 dirnames 裡的目錄已經在 dirnames yield 給呼叫者之前被產生。

預設來自 os.scandir() 的錯誤會被忽略。如果指定了可選引數 on_error(它應該要是一個可呼叫物件),它會被以一個 OSError 實例為引數來呼叫。這個可呼叫物件可以處理錯誤以繼續走訪,或者再次引發錯誤來停止走訪。注意,檔案名稱可以從例外物件的 filename 屬性來取得。

預設 Path.walk() 不會跟隨符號連結,而是會把它們加到 filenames 串列。將 follow_symlinks 設定為 true 會解析符號連結,並將它們根據其指向的目標放在適當的 dirnamesfilenames,而因此訪問到符號連結指向的目錄(在有支援符號連結的地方)。

備註

需要注意的是如果符號連結指向一個其本身的父目錄,則將 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() 不允許在目錄為空之前刪除它:

# Delete everything reachable from the directory "top".
# CAUTION:  This is dangerous! For example, if top == Path('/'),
# it could delete all of your files.
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 版被加入.

建立檔案與目錄

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

根據給定路徑來建立一個檔案。如果 mode 有給定,它會與行程的 umask 值結合,以確定檔案模式和存取旗標。當檔案已經存在時,若 exist_ok 為 true 則函式不會失敗(其變更時間會被更新為當下時間),否則會引發 FileExistsError

也參考

The open(), write_text() and write_bytes() methods are often used to create files.

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

在給定路徑下建立一個新的目錄。如果有給 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() 相反。

使這個路徑成為與 target 相同檔案的一個硬連結 (hard link)。

備註

引數的順序 (link, target) 和 os.link() 相反。

在 3.10 版被加入.

Renaming and deleting

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'

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

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

在 3.8 版的變更: 新增了回傳值,回傳新的 Path 實例。

Path.replace(target)

將此檔案或目錄重新命名為給定的 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 參數。

Path.rmdir()

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

Permissions and ownership

Path.owner()

回傳擁有該檔案的用戶名稱。如果在系統資料庫中找不到該檔案的使用者識別字 (UID),則會引發 KeyError

Path.group()

回傳擁有該檔案的群組名稱。如果在系統資料庫裡找不到檔案的群組識別字 (GID) 會引發 KeyError

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

修改檔案模式 (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.lchmod(mode)

類似 Path.chmod(),但如果該路徑指向一個符號連結,則符號連結的模式 (mode) 會被改變而不是其指向的目標。

os 模組裡的工具的對應關係

以下是一張表格,對應許多 os 函式及其相符於 PurePath/Path 的項目。

osos.path

pathlib

os.path.dirname()

PurePath.parent

os.path.basename()

PurePath.name

os.path.splitext()

PurePath.stemPurePath.suffix

os.path.join()

PurePath.joinpath()

os.path.isabs()

PurePath.is_absolute()

os.path.relpath()

PurePath.relative_to() [1]

os.path.expanduser()

Path.expanduser() [2]

os.path.realpath()

Path.resolve()

os.path.abspath()

Path.absolute() [3]

os.path.exists()

Path.exists()

os.path.isfile()

Path.is_file()

os.path.isdir()

Path.is_dir()

os.path.islink()

Path.is_symlink()

os.path.isjunction()

Path.is_junction()

os.path.ismount()

Path.is_mount()

os.path.samefile()

Path.samefile()

os.getcwd()

Path.cwd()

os.stat()

Path.stat()

os.lstat()

Path.lstat()

os.listdir()

Path.iterdir()

os.walk()

Path.walk() [4]

os.mkdir()os.makedirs()

Path.mkdir()

os.link()

Path.hardlink_to()

os.symlink()

Path.symlink_to()

os.readlink()

Path.readlink()

os.rename()

Path.rename()

os.replace()

Path.replace()

os.remove()os.unlink()

Path.unlink()

os.rmdir()

Path.rmdir()

os.chmod()

Path.chmod()

os.lchmod()

Path.lchmod()

註解