Сообщить об ошибке.

Манипуляции с путями файловой системы средствами pathlib

Получение компонентов, сравнение и проверка пути файловой системы

Описанные ниже свойства и методы позволяют легко манипулировать с путями файловой системы без осуществления системных вызовов. Другими словами, при помощи этого класса можно проводить операции с путями, которых нет в файловой системе.

Данные методы принадлежат экземпляру, созданному из класса PurePath(), стандартного модуля pathlib.

Содержание:

Примечание: Все приведенные ниже операции поддерживаются классом pathlib.Path(), т.к. он является подклассом pathlib.PurePath().


PurePath.parts:

Свойство PurePath.parts возвращает кортеж, дающий доступ к отдельным частям/компонентам пути. Полученный кортеж представляет собой последовательность сегментов пути, проанализированных на основе значения разделителя пути.

Обратите внимание, как диск и локальный корень перегруппированы в одну часть.

>>> import pathlib
>>> p = pathlib.PurePath('/usr/bin/python3')
>>> p.parts
# ('/', 'usr', 'bin', 'python3')

>>> p = pathlib.PurePath('c:/Program Files/PSF')
>>> p.parts
# ('c:\\', 'Program Files', 'PSF')

PurePath.drive:

Свойство PurePath.drive возвращает строку, представляющую букву или имя диска, если есть:

>>> import pathlib
>>> pathlib.PurePath('c:/Program Files/').drive
# 'c:'
>>> pathlib.PurePath('/Program Files/').drive
# ''
>>> pathlib.PurePath('/etc').drive
# ''

Расширения UNC также считаются дисками:

>>> import pathlib
>>> pathlib.PurePath('//host/share/foo.txt').drive
# '\\\\host\\share'

PurePath.root:

Свойство PurePath.root возвращает строку, представляющую локальный или глобальный корень, если есть:

>>> import pathlib
>>> pathlib.PurePath('c:/Program Files/').root
# '\\'
>>> pathlib.PurePath('c:Program Files/').root
# ''
>>> pathlib.PurePath('/etc').root
# '/'

У UNC расширения тоже всегда есть корень:

>>> import pathlib
>>> pathlib.PurePath('//host/share').root
# '\\'

PurePath.anchor:

Свойство PurePath.anchor возвращает строку, представляющую конкатенацию диска и корня:

>>> import pathlib
>>> pathlib.PurePath('c:/Program Files/').anchor
# 'c:\\'
>>> pathlib.PurePath('c:Program Files/').anchor
# 'c:'
>>> pathlib.PurePath('/etc').anchor
# '/'
>>> pathlib.PurePath('//host/share').anchor
# '\\\\host\\share\\'

PurePath.parents:

Свойство PurePath.parents представляет собой неизменную последовательность, обеспечивающую доступ к логическим предкам пути:

Изменено в Python 3.10: PurePath.parents теперь поддерживает срезы и отрицательные значения индекса.

>>> import pathlib
>>> p = pathlib.PurePath('c:/foo/bar/setup.py')
>>> p.parents[0]
# PureWindowsPath('c:/foo/bar')
>>> p.parents[1]
# PureWindowsPath('c:/foo')
>>> p.parents[2]
# PureWindowsPath('c:/')

# Двигаемся вверх по директории
>>> for up in p.parents:
...     print(up)
... 
# c:\foo\bar
# c:\foo
# c:\

PurePath.parent:

Свойство PurePath.parent возвращает строку, представляющую логический родительский путь:

>>> import pathlib
>>> p = pathlib.PurePath('/a/b/c/d')
>>> p.parent
# PurePosixPath('/a/b/c')

Свойство не позволяет пройти мимо корневой директории или пустого пути:

>>> import pathlib
>>> p = pathlib.PurePath('/')
>>> p.parent
# PurePosixPath('/')
>>> p = pathlib.PurePath('.')
>>> p.parent
# PurePosixPath('.')

Заметка. Это чисто лексическая операция, отсюда и следующее поведение:

>>> import pathlib
>>> p = pathlib.PurePath('foo/..')
>>> p.parent
# PurePosixPath('foo')

Если необходимо вычислить произвольный путь файловой системы вверх, рекомендуется сначала вызвать Path.resolve(), чтобы разрешить символические ссылки и исключить компоненты '..'.

PurePath.name:

Свойство PurePath.name возвращает строку, представляющую конечный компонент пути, исключая диск и корень, если есть. Другими словами это имя файла или название последней директории в пути.

>>> import pathlib
>>> pathlib.PurePath('my/library/setup.py').name
# 'setup.py'

Имена дисков UNC не учитываются:

>>> import pathlib
>>> pathlib.PurePath('//some/share/setup.py').name
# 'setup.py'
>>> pathlib.PurePath('//some/share').name
# ''

PurePath.suffix:

Свойство PurePath.suffix возвращает строку, представляющую расширение файла, если есть:

>>> import pathlib
>>> pathlib.PurePath('my/library/setup.py').suffix
# '.py'
>>> pathlib.PurePath('my/library.tar.gz').suffix
# '.gz'
>>> pathlib.PurePath('my/library').suffix
# ''

PurePath.suffixes:

Свойство PurePath.suffixes возвращает список, представляющий расширения файла, если есть:

>>> import pathlib
>>> pathlib.PurePath('my/library.tar.gar').suffixes
# ['.tar', '.gar']
>>> pathlib.PurePath('my/library.tar.gz').suffixes
# ['.tar', '.gz']
>>> pathlib.PurePath('my/library').suffixes
# []

PurePath.stem:

Свойство PurePath.stem возвращает строку, представляющую последний компонент пути без суффикса:

>>> import pathlib
>>> pathlib.PurePath('my/library.tar.gz').stem
# 'library.tar'
>>> pathlib.PurePath('my/library.tar').stem
# 'library'
>>> pathlib.PurePath('my/library').stem
# 'library'

PurePath.as_posix():

Метод PurePath.as_posix() возвращает строковое представление пути с косыми чертами '/':

>>> import pathlib
>>> p = pathlib.PurePath('c:\\windows')
>>> str(p)
# 'c:\\windows'
>>> p.as_posix()
# 'c:/windows'

PurePath.as_uri():

Метод PurePath.as_uri() возвращает строку, представляющую путь как file URI. если путь не абсолютен, то поднимается исключение ValueError.

>>> import pathlib
>>> p = PurePath('/etc/passwd')
>>> p.as_uri()
# 'file:///etc/passwd'
>>> p = PurePath('c:/Windows')
>>> p.as_uri()
# 'file:///c:/Windows'

PurePath.is_absolute():

Метод PurePath.is_absolute() проверяет, является ли путь абсолютным или нет. Возвращает True, если путь считается абсолютным. Путь считается абсолютным, если он имеет как корень так и диск, если это позволяет файловая система:

>>> import pathlib
>>> pathlib.PurePath('/a/b').is_absolute()
# True
>>> pathlib.PurePath('a/b').is_absolute()
# False

>>> pathlib.PurePath('c:/a/b').is_absolute()
# True
>>> pathlib.PurePath('/a/b').is_absolute()
# False
>>> pathlib.PurePath('c:').is_absolute()
# False
>>> pathlib.PurePath('//some/share').is_absolute()
# True

PurePath.is_relative_to(*other):

Новое в версии Python 3.9.

Метод PurePath.is_relative_to() возвращает значение True, если путь PurePath является относительным пути other.

>>> from pathlib import PurePath
>>> p = PurePath('/etc/passwd')
>>> p.is_relative_to('/etc')
# True
>>> p.is_relative_to('/usr')
# False

Передача дополнительных позиционных аргументов устарела c версии Python 3.12, будет удалено в Python 3.14. Если все-же они предоставлены, то они соединяются с other.

PurePath.is_reserved():

Метод PurePath.is_reserved() c pathlib.PureWindowsPath возвращает True, если путь считается зарезервированным под Windows и False противном случае. С pathlib.PurePosixPath, всегда возвращает False.

>>> import pathlib
>>> pathlib.PurePath('nul').is_reserved()
# True
>>> pathlib.PurePath('nul').is_reserved()
# False

Вызовы файловой системы на зарезервированных путях под Windows могут таинственно завершаться сбоем или иметь непредвиденные последствия.

PurePath.joinpath(*other):

Метод PurePath.joinpath() объединяет исходный путь с каждым из аргументов other по очереди:

>>> import pathlib
>>> pathlib.PurePath('/etc').joinpath('passwd')
# PurePosixPath('/etc/passwd')
>>> pathlib.PurePath('/etc').joinpath(PurePosixPath('passwd'))
# PurePosixPath('/etc/passwd')
>>> pathlib.PurePath('/etc').joinpath('init.d', 'apache2')
# PurePosixPath('/etc/init.d/apache2')
>>> pathlib.PurePath('c:').joinpath('/Program Files')
# PureWindowsPath('c:/Program Files')

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

Изменено в версии Python 3.12: Добавлен аргумент case_sensitivity.

Метод PurePath.match() сравнивает исходный путь с предоставленным шаблоном pattern в стиле модуля glob. Метод PurePath.match вернет True если сопоставление прошло успешно и False в противном случае.

Если шаблон pattern является относительным по отношению к сравниваемому пути. Сравниваемый путь может быть как относительным так и абсолютным, а сопоставление выполняется справа:

>>> import pathlib
>>> pathlib.PurePath('a/b.py').match('*.py')
# True
>>> pathlib.PurePath('/a/b/c.py').match('b/*.py')
# True
>>> pathlib.PurePath('/a/b/c.py').match('a/*.py')
# False

Если шаблон pattern является абсолютным, то и путь должен быть абсолютным и весь путь должен совпадать:

>>> import pathlib
>>> pathlib.PurePath('/a.py').match('/*.py')
# True
>>> pathlib.PurePath('a/b.py').match('/*.py')
# False

Шаблон pattern может быть другим объектом пути; это ускоряет сопоставление одного и того же шаблона с несколькими файлами:

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

Как и в других методах, чувствительность к регистру соответствует настройкам платформы по умолчанию:

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

Аргумент case_sensitivity (добавлен в Python 3.12) отвечает за чувствительность к регистру при сравнении. Для переопределения поведения принимает значение True или False.

PurePath.relative_to(*other, walk_up=False):

Метод PurePath.relative_to() вычисляет версию исходного пути относительно переданного в качестве аргумента пути other. Если это невозможно, то поднимается исключение ValueError:

>>> import pathlib
>>> p = pathlib.PurePath('/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 694, in relative_to
#     .format(str(self), str(formatted)))
# ValueError: '/etc/passwd' does not start with '/usr'

Если аргумент walk_up (добавлен в Python 3.12) имеет значение 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, поскольку он предполагает, что в пути нет символических ссылок. То есть, если необходимо разрешить символические ссылки, то сначала нужно вызвать метод Path.resolve().

Изменено в версии Python 3.12: добавлен аргумент walk_up (старое поведение такое же, как walk_up=False).

Передача дополнительных позиционных аргументов устарела c версии Python 3.12, будет удалено в Python 3.14. Если все-же они предоставлены, то они соединяются с other.

PurePath.with_name(name):

Метод PurePath.with_name() возвращает новый объект пути с измененным name. Если исходный путь не имеет имени name, вызывается исключение ValueError:

>>> import pathlib
>>> p = pathlib.PurePath('c:/Downloads/pathlib.tar.gz')
>>> p.with_name('setup.py')
# PureWindowsPath('c:/Downloads/setup.py')
>>> p = pathlib.PurePath('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):

Новое в версии Python 3.9.

Метод PurePath.with_stem() возвращает новый путь с измененной основой stem. Если исходный путь PurePath не имеет имени, то вызывается 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

Новое в версии Python 3.9.

PurePath.with_suffix(suffix):

Метод PurePath.with_suffix() возвращает новый объект пути с измененным suffix. Если исходный путь не имеет расширения suffix, то к окончанию пути тупо добавляется переданный suffix .

Если суффикс suffix='' - является пустой строкой, исходный суффикс удаляется:

>>> import pathlib
>>> p = pathlib.PurePath('c:/Downloads/pathlib.tar.gz')
>>> p.with_suffix('.bz2')
# PureWindowsPath('c:/Downloads/pathlib.tar.bz2')
>>> p = pathlib.PurePath('README')
>>> p.with_suffix('.txt')
# PureWindowsPath('README.txt')
>>> p = pathlib.PurePath('README.txt')
>>> p.with_suffix('')
# PureWindowsPath('README')

PurePath.with_segments(*pathsegments):

Новое в версии Python 3.12.

Метод PurePath.with_segments() создает новый объект пути того же типа, объединив заданные сегменты пути *pathsegments.

Этот метод вызывается всякий раз, когда создается производный путь, например, от PurePath.parent и PurePath.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