Python內建庫:pathlib(檔案路徑操作)

山上下了雪-bky發表於2024-05-19

官方文件: pathlib — Object-oriented filesystem paths

一、基礎使用

  • 遍歷子目錄
  • 使用萬用字元遍歷檔案
  • 拼接路徑
  • 獲取標準化後的絕對路徑
  • 查詢路徑常規屬性
  • 開啟檔案
from pathlib import Path

print('1.1 查詢指定目錄的子目錄')
p = Path('D:/Envs')
print([sub_p for sub_p in p.iterdir() if sub_p.is_dir()])

print('1.2 使用萬用字元查詢目錄中的某類檔案')
p = Path('D:/Envs/flask_env/Scripts')
# glob的結果是一個生成器,需要使用list進行轉換
print(list(p.glob('*.bat')))

print('1.3 拼接路徑,以下三種方式都可以')
p = Path('D:/Envs')
p = p / 'flask_env'
print(p)
p = p.joinpath('Scripts')
print(p)
p = p.joinpath(Path('activate.bat'))
print(p)

print('1.4 獲取絕對路徑,會自動消除符號連結使之稱為一個標準化的路徑表示,Windows中,斜槓會被轉換為反斜槓')
p = Path('.')
print(p.resolve())

print('1.5 查詢路徑常規屬性')
p = Path('D:/Envs')
print(p.exists())
print(p.is_dir())
print(p.is_file())

print('1.6 開啟檔案,以下兩種方式都可以')
p = Path('./test.txt')
with open(p) as f:
    print(f.read())
with p.open() as f:
    print(f.read())
1.1 查詢指定目錄的子目錄
[WindowsPath('D:/Envs/django_env'), WindowsPath('D:/Envs/flask_env'), WindowsPath('D:/Envs/study')]

1.2 使用萬用字元查詢目錄中的某類檔案
[WindowsPath('D:/Envs/flask_env/Scripts/activate.bat'), WindowsPath('D:/Envs/flask_env/Scripts/deactivate.bat')]

1.3 拼接路徑,以下三種方式都可以
D:\Envs\flask_env
D:\Envs\flask_env\Scripts
D:\Envs\flask_env\Scripts\activate.bat

1.4 獲取絕對路徑,會自動消除符號連結使之成為一個標準化的路徑表示,Windows中,斜槓會被轉換為反斜槓
D:\Projects\pathlib_test

1.5 查詢路徑常規屬性
True
True
False

1.6 開啟檔案,以下兩種方式都可以
This is a test file
This is a test file

二、Pure paths

Pure paths在不對檔案系統進行實際操作的前提下,提供了各種操作路徑的方法。該模組提供了三個類PurePath、PureWindowsPath、PurePosixPath,從名稱可以看出PureWindowsPath用於Windows系統,PurePosixPath用於非Windows系統,當然也可以直接使用基類PurePath,從類定義上看,PureWindowsPath和PurePosixPath只是在 _flavour 上提前定義好了作業系統型別,直接使用PurePath會根據 os.name 自動識別當前作業系統。

注: 本章節示例來自官方文件pathlib — Object-oriented filesystem paths

2.1 初始化

初始化時可以傳入一個或多個引數,引數可以是路徑字串,也可以是 pathlib.Path 物件,若沒有傳入任何引數,則預設為當前目錄。

>>> PurePath('setup.py')      # Running on a Unix machine
PurePosixPath('setup.py')
>>> PurePath('foo', 'some/path', 'bar')
PurePosixPath('foo/some/path/bar')
>>> PurePath(Path('foo'), Path('bar'))
PurePosixPath('foo/bar')
>>> PurePath()
PurePosixPath('.')

路徑中間的 //. 會被自動最佳化。

>>> PurePath('foo//bar')
PurePosixPath('foo/bar')
>>> PurePath('//foo/bar')
PurePosixPath('//foo/bar')
>>> PurePath('foo/./bar')
PurePosixPath('foo/bar')
>>> PurePath('foo/../bar')
PurePosixPath('foo/../bar')

2.2 通用屬性

一個 PurePath 或 其子類,都可以直接用在任何實現了 os.PathLike 介面的地方,並且如果想要 PurePath 物件代表的路徑的字串值,直接使用str即可。

>>> import os
>>> p = PurePath('/etc')
>>> os.fspath(p)
'/etc'
>>> p = PurePath('/etc')
>>> str(p)
'/etc'
>>> bytes(p)
b'/etc'
>>> p = PureWindowsPath('c:/Program Files')
>>> str(p)
'c:\\Program Files'

parts 屬性提供了根據路徑分隔符分隔的元組。

>>> p = PurePath('/usr/bin/python3')
>>> p.parts
('/', 'usr', 'bin', 'python3')
>>> p = PureWindowsPath('c:/Program Files/PSF')
>>> p.parts
('c:\\', 'Program Files', 'PSF')

2.3 其他方法和屬性

PurePath.drive

獲取路徑中的磁碟機代號(如果有),否則返回空字串。

PurePath.anchor

PurePath.drivePurePath.root 的結合。

>>> PureWindowsPath('c:/Program Files/').anchor
'c:\\'
>>> PureWindowsPath('c:Program Files/').anchor
'c:'
>>> PurePosixPath('/etc').anchor
'/'
>>> PureWindowsPath('//host/share').anchor  # UNC shares
'\\\\host\\share\\'

PurePath.parents

返回一個儲存了各個祖先節點的不可變序列。在 Python 3.10 開始,支援對其切片以及使用負向索引。

>>> 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:/')

PurePath.parent

返回上一級路徑。注意,這個方法只是個“字串上的切割”,不會查詢實際的路徑。

>>> p = PurePosixPath('/a/b/c/d')
>>> p.parent
PurePosixPath('/a/b/c')
>>> p = PurePosixPath('foo/..')  # 如果想要實際的路徑資訊,可以使用Path物件,先呼叫Path.resolve()獲取絕對路徑
>>> p.parent
PurePosixPath('foo')

PurePath.name

按路徑分割後,返回最後一級名稱(會自動去除磁碟機代號 drive 和根路徑符 root )。

PurePosixPath('my/library/setup.py').name
'setup.py'

PurePath.suffix

返回路徑中的檔名字尾(如果有),如 .py

PurePath.suffixes

返回路徑中最後一級的檔名字尾列表(如果有),如“library.tar.gz”的suffixes值為 ['.tar', '.gz']

PurePath.stem

返回路徑中最後一級的檔名(不含字尾 PurePath.suffix ),如“library.tar.gz”的stem值為 library.tar

PurePath.as_posix()

返回以斜槓表示的路徑。

PurePath.is_absolute()

是否為絕對路徑。

PurePath.joinpath(*pathsegments)

拼接路徑,可以傳入一個或多個字串或Path物件。

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

判斷路徑是否符合指定萬用字元模式。 case_sensitive 引數( Python 3.12 增加)在Windows系統預設為False,其他系統預設為True。如果 pattern 也是PurePath物件,此方法匹配效率會更高。

>>> 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('*.py')
>>> PurePath('a/b.py').match(pattern)
True

PurePath.with_name(name)

使用指定的name替換原有的name,如果原路徑就沒有name,則丟擲異常。

>>> 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替換原有的stem,如果原路徑就沒有stem,則丟擲異常。

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

PurePath.with_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')

三、path實體

path實體也提供了三個類Path(基類)、PosixPath、WindowsPath,Path繼承自PurePath,所以PurePath支援的操作,path實體的三個類也是支援的。path實體與pure path區別在於,path實體物件支援系統操作,如獲取絕對路徑、遍歷目錄的所有子目錄和檔案、開啟檔案等,所以需要特別注意,在使用Path類時,可能會因為系統不支援導致丟擲OSError等異常。

注: 本章節部分示例來自官方文件pathlib — Object-oriented filesystem paths

3.1 常用方法

Path.cwd()

返回當前路徑,同 os.getcwd()

Path.home()

返回當前使用者的home目錄,同 os.path.expanduser()

Path.stat(*, follow_symlinks=True)

獲取路徑詳細資訊,同 os.stat()follow_symlinks 引數在 Python 3.10 開始新增。

>>> p = Path('setup.py')
>>> p.stat().st_size
956
>>> p.stat().st_mtime
1327883547.852554

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

修改檔案許可權,同 os.chmod()follow_symlinks 引數在 Python 3.10 新增。

>>> p = Path('setup.py')
>>> p.stat().st_mode
33277
>>> p.chmod(0o444)
>>> p.stat().st_mode
33060

Path.exists(*, follow_symlinks=True)

檢查路徑是否存在。 follow_symlinks 引數在 Python 3.12 新增。

Path.expanduser()

返回填充了home目錄的路徑。該方法在 Python 3.5 新增。

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

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

使用萬用字元遍歷當前路徑下的所有目錄和檔案。 case_sensitivePython 3.12 新增)預設為None,即使用當前系統的大小寫規則,也可手動指定。當 pattern 以路徑分隔符結尾,則只會列出目錄,不會列出檔案(該特性在 Python 3.11 新增)。

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

Path.group()

返回路徑的屬組。

Path.is_dir()

檢查路徑是否是目錄。

Path.is_file()

檢查路徑是否是檔案。

Path.is_junction()

檢查路徑是否是junction快捷方式(Windows系統專用)。

Path.is_mount()

判斷路徑是否是一個掛載點(該方法在 Python 3.7 新增,在 Python 3.12 支援Windows系統)。

Path.is_symlink()

判斷路徑是否是符號連結,如果路徑不存在也會返回False。

Path.is_socket()

檢查路徑是否指向Unix socket檔案,如果路徑不存在也會返回False。

Path.is_fifo()

檢查路徑是否指向FIFO儲存,如果路徑不存在也會返回False。

Path.is_block_device()

檢查路徑是否指向塊裝置,如果路徑不存在也會返回False。

Path.is_char_device()

檢查路徑是否指字元裝置,如果路徑不存在也會返回False。

Path.iterdir()

以生成器的方式遍歷路徑下的所有目錄和檔案。

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

該方法在 Python 3.12 新增。遞迴遍歷指定路徑下的所有目錄和檔案,使用時由生成器每次生成一個三元組(當前遍歷目錄,子目錄名列表,子檔名列表),想要使用某個子目錄或子檔案時,其全路徑為“當前遍歷目錄+目錄名/檔名”。

  • top_down 預設為True,即從上到下遍歷,為False時表示從下到上遍歷,“上下”的區別就是從當前目錄的子目錄開始往最裡一層一層遍歷遍歷,還是從最深的子目錄往外一層一層遍歷。
  • on_error 預設為None,即忽略walk過程中的異常,也可手動指定一個可呼叫物件來處理異常,該物件的要求是接受發生的異常(OSError物件)。
  • follow_symlinks 預設為False,即在walk時,不會自動跟蹤連結到真實的路徑,列出的結果就是連結本身(該操作區別於 os.walk() )。

示例:有路徑結構如下

test1
  - test2
    - test2.txt
  - test1.txt
>>> import pathlib
>>> p = pathlib.Path('Z:\\Projects\\Daily Test\\pathlib_test\\test1')
>>> for root, dirnames, filenames in p.walk():
        print(root)
        print(dirnames)
        print(filenames)

    
    Z:\Projects\Daily Test\pathlib_test\test1
    ['test2']
    ['test1.txt']
    Z:\Projects\Daily Test\pathlib_test\test1\test2
    []
    ['test2.txt']
>>> 
>>> for root, dirnames, filenames in p.walk(top_down=False):
        print(root)
        print(dirnames)
        print(filenames)

    
    Z:\Projects\Daily Test\pathlib_test\test1\test2
    []
    ['test2.txt']
    Z:\Projects\Daily Test\pathlib_test\test1
    ['test2']
    ['test1.txt']

Path.lchmod(mode)

類似 Path.chmod() ,修改檔案許可權,區別在於,如果路徑是一個連結,則只會修改連結本身,而連結指向的物件不會被修改。

Path.lstat()

類似 Path.stat() ,修改檔案屬性,區別在於,如果路徑是一個連結,則只會修改連結本身,而連結指向的物件不會被修改。

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

建立目錄。 parents 預設False,表示路徑中的某個父目錄不存在則會拋錯, exist_ok 預設為False(該引數在 Python 3.5 新增),表示建立的路徑已經存在則會拋錯,這兩個引數的行為與POSIX系統中的 mkdir -p 命令執行一致。

Path.open(mode='r', buffering=-1, encoding=None, errors=None, newline=None)

開啟檔案,同內建的open函式。

Path.owner()

返回路徑的屬主。

Path.read_bytes()

以byte型別返回檔案的二進位制內容。(該方法在 Python 3.5 新增)

Path.read_text(encoding=None, errors=None)

返回解碼後的檔案文字內容。檔案開啟後會立即關閉,引數的行為與內建的open函式相同。(該方法在 Python 3.5 新增)

Path.readlink()

返回連結指向的真實檔案的路徑,同 os.readlink() 。(該方法在 Python 3.9 新增)

Path.rename(target)

重新命名檔案或目錄,並返回新的路徑物件(返回值在 Python 3.8 新增)。在Unix是上靜默修改,在Windows上則會修改失敗。同 os.rename()

Path.replace(target)

替換一個已有的檔案或目錄,並返回新的路徑物件(返回值在 Python 3.8 新增),如果待替換的路徑為已存在的檔案或空目錄,則會強制替換。

Path.absolute()

返回絕對路徑,但不會自動標準化路徑,也不會自動解析符號連結。

Path.resolve(strict=False)

返回Path物件的絕對路徑,會自動消除符號連結、“.”、“..”等格式的路徑。當 strict=True 且檔案路徑不存在時,則丟擲異常。(該引數在 Python 3.6 新增,在這之前版本預設為True)

>>> p = Path()
>>> p
PosixPath('.')
>>> p.resolve()
PosixPath('/home/antoine/pathlib')
>>> p = Path('docs/../setup.py')
>>> p.resolve()
PosixPath('/home/antoine/pathlib/setup.py')

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

按照給定萬用字元模式遞迴遍歷子目錄及檔案。 pattern 引數若以路徑分隔符結尾,則只遍歷所有子目錄,不會遍歷檔案(該規則在 Python 3.11 新增)。 case_sensitive 預設為None,即跟隨系統大小寫規則。(該引數在 Python 3.12 新增)。

Path.rmdir()

移除指定空目錄(非空目錄無法移除)。

Path.samefile(other_path)

判斷兩個檔案是否相等, other_path 可以是Path物件,也可以是字串。(該方法在 Python 3.5 新增)

Path.symlink_to(target, target_is_directory=False)

使當前Path物件成為一個符號連結,並指向 target 所表示的檔案。 target_is_directory 引數在非Windows系統上會被忽略,不生效。

Path.hardlink_to(target)

使當前Path物件成為一個硬連結,並指向 target 所表示的檔案。

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

建立一個路徑,如果 exist_ok=False 且路徑已經存在,則會丟擲異常。

Path.unlink(missing_ok=False)

移除檔案或符號連結。如果此Path物件指向的是目錄,請使用 Path.rmdir()missing_ok 預設為False,即路徑不存在時丟擲異常,反之則忽略異常。(該引數在 Python 3.8 新增)

Path.write_bytes(data)

以位元組模式開啟檔案並寫入位元組資料,寫入完成自動關閉檔案。

Path.write_text(data, encoding=None, errors=None, newline=None)

以文字模式開啟檔案並寫入文字資料,同內建的open函式。(該方法在 Python 3.5 新增, newline 引數在 Python 3.10 新增)

相關文章