Документация Python неофициальный перевод
Содержание страницы

11.1. pathlib – объектно-ориентированные пути файловой системыpathlib – Object-oriented filesystem paths

Новое в версии 3.4.

Этот модуль предоставляет классы, представляющие пути файловой системы с семантикой, подходящей для разных операционных систем. Классы путей делятся на чистые пути, которые выполняют только вычислительные операции без ввода-вывода, и конкретные пути, которые наследуют чистые пути, но также предоставляют операции ввода-вывода.

../_images/pathlib-inheritance.png

Если вы никогда не использовали этот модуль раньше или просто не уверены, какой класс подходит для вашей задачи, скорее всего, вам нужен Path. Он создаёт экземпляр конкретного пути для платформы, на которой выполняется код.

Чистые пути полезны в некоторых особых случаях; например:

  1. Если требуется работать с путями Windows на машине с Unix (или наоборот). Нельзя создать экземпляр WindowsPath при работе в Unix, но можно создать экземпляр PureWindowsPath.
  2. Если нужно, чтобы код только манипулировал путями без фактического обращения к ОС. В таком случае может быть полезно создать экземпляр одного из чистых классов, поскольку они просто не имеют операций доступа к ОС.

Примечание

Этот модуль был включён в стандартную библиотеку на временной основе. Обратно несовместимые изменения (вплоть до удаления пакета) могут быть внесены, если основные разработчики сочтут это необходимым.

См. также

PEP 428: модуль pathlib – объектно-ориентированные пути файловой системы.

См. также

Для низкоуровневых манипуляций с путями в виде строк можно также использовать модуль os.path.

11.1.1. Основное использованиеBasic use

Импорт основного класса:

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

11.1.2. Чистые путиPure paths

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

class pathlib.PurePath(*pathsegments)

Обобщённый класс, представляющий вариант пути, принятый в системе (при создании экземпляра порождает либо PurePosixPath, либо PureWindowsPath):

>>> PurePath('setup.py')      # Запуск на Unix-машине
PurePosixPath('setup.py')

Каждый элемент pathsegments может быть либо строкой, представляющей сегмент пути, либо другим объектом пути:

>>> 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 смена локального корня не отбрасывает предыдущую настройку диска:

>>> PureWindowsPath('c:/Windows', '/Program Files')
PureWindowsPath('c:/Program Files')

Лишние косые черты и одиночные точки схлопываются, но двойные точки ('..') – нет, так как это изменило бы смысл пути при наличии символических ссылок:

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

(наивный подход сделал бы PurePosixPath('foo/../bar') эквивалентным PurePosixPath('bar'), что неверно, если foo – символическая ссылка на другой каталог)

class pathlib.PurePosixPath(*pathsegments)

Подкласс PurePath, представляющий пути файловых систем, отличных от Windows:

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

pathsegments задаётся аналогично PurePath.

class pathlib.PureWindowsPath(*pathsegments)

Подкласс PurePath, представляющий пути файловой системы Windows:

>>> PureWindowsPath('c:/Program Files/')
PureWindowsPath('c:/Program Files')

pathsegments задаётся аналогично PurePath.

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

11.1.2.1. Общие свойстваGeneral properties

Пути неизменяемы и хешируемы. Пути одного варианта сравнимы и упорядочиваемы. Эти свойства учитывают семантику регистрозависимости данного варианта:

>>> 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: unorderable types: PureWindowsPath() < PurePosixPath()

11.1.2.2. ОператорыOperators

Оператор косой черты помогает создавать дочерние пути, аналогично os.path.join():

>>> p = PurePath('/etc')
>>> p
PurePosixPath('/etc')
>>> p / 'init.d' / 'apache2'
PurePosixPath('/etc/init.d/apache2')
>>> q = PurePath('bin')
>>> '/usr' / q
PurePosixPath('/usr/bin')

Строковое представление пути – это сам сырой путь файловой системы (в нативном виде, например с обратными слешами в 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'

Примечание

Вызов bytes рекомендуется только в Unix. В Windows представление в виде строки Unicode является каноническим для путей файловой системы.

11.1.2.3. Доступ к отдельным частямAccessing individual parts

Для доступа к отдельным «частям» (компонентам) пути используйте следующее свойство:

PurePath.parts

Кортеж, предоставляющий доступ к различным компонентам пути:

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

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

(обратите внимание, как диск и локальный корень объединены в одну часть)

11.1.2.4. Методы и свойстваMethods and properties

Чистые пути предоставляют следующие методы и свойства:

PurePath.drive

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

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

UNC-ресурсы также считаются дисками:

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

Строка, представляющая (локальный или глобальный) корень, если таковой имеется:

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

UNC-ресурсы всегда имеют корень:

>>> PureWindowsPath('//host/share').root
'\\'
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

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

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

Нельзя выйти за пределы anchor или пустого пути:

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

Примечание

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

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

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

PurePath.name

Строка, представляющая последний компонент пути, исключая диск и корневой каталог (если они есть):

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

Последний компонент пути без суффикса:

>>> 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_reserved()

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

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

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

PurePath.joinpath(*other)

Вызов этого метода эквивалентен последовательному объединению пути с каждым из аргументов other:

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

Сопоставляет этот путь с заданным шаблоном в стиле glob. Возвращает 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

Как и в случае с другими методами, учитывается регистр символов:

>>> PureWindowsPath('b.py').match('*.PY')
True
PurePath.relative_to(*other)

Вычисляет версию этого пути относительно пути, представленного 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 694, in relative_to
    .format(str(self), str(formatted)))
ValueError: '/etc/passwd' does not start with '/usr'
PurePath.with_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_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')

11.1.3. Конкретные путиConcrete paths

Конкретные пути – это подклассы чистых классов путей. В дополнение к операциям, предоставляемым последними, они также предоставляют методы для выполнения системных вызовов над объектами путей. Есть три способа создания конкретных путей:

class pathlib.Path(*pathsegments)

Подкласс PurePath, этот класс представляет конкретные пути системного типа (при создании экземпляра создаётся либо PosixPath, либо WindowsPath):

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

pathsegments задаётся аналогично PurePath.

class pathlib.PosixPath(*pathsegments)

Подкласс Path и PurePosixPath, этот класс представляет конкретные пути файловой системы, отличные от Windows:

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

pathsegments задаётся аналогично PurePath.

class pathlib.WindowsPath(*pathsegments)

Подкласс Path и PureWindowsPath, этот класс представляет конкретные пути файловой системы Windows:

>>> WindowsPath('c:/Program Files/')
WindowsPath('c:/Program Files')

pathsegments задаётся аналогично PurePath.

Можно создать экземпляр только того flavour класса, который соответствует системе (использование системных вызовов для несовместимых flavour путей может привести к ошибкам или сбоям в приложении):

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

11.1.3.1. МетодыMethods

Конкретные пути предоставляют следующие методы в дополнение к методам чистых путей. Многие из этих методов могут возбуждать OSError, если системный вызов завершается ошибкой (например, если путь не существует):

classmethod Path.cwd()

Возвращает новый объект пути, представляющий текущий каталог (как возвращается os.getcwd()):

>>> Path.cwd()
PosixPath('/home/antoine/pathlib')
Path.stat()

Возвращает информацию об этом пути (аналогично os.stat()). Результат запрашивается при каждом вызове этого метода.

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

Изменяет режим и права доступа к файлу, как os.chmod():

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

Указывает ли путь на существующий файл или каталог:

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

Примечание

Если путь указывает на символическую ссылку, exists() возвращает, указывает ли символическая ссылка на существующий файл или каталог.

Path.glob(pattern)

Выполняет поиск по заданному шаблону в каталоге, представленном этим путём, возвращая все соответствующие файлы (любого типа):

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

Возвращает имя группы-владельца файла. KeyError возбуждается, если gid файла не найден в системной базе данных.

Path.is_dir()

Возвращает True, если путь указывает на каталог (или символическую ссылку, указывающую на каталог), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.is_file()

Возвращает True, если путь указывает на обычный файл (или символическую ссылку, указывающую на обычный файл), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Возвращает True, если путь указывает на символическую ссылку, и False в противном случае.

False также возвращается, если путь не существует; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.is_socket()

Возвращает True, если путь указывает на сокет Unix (или символическую ссылку, указывающую на сокет Unix), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.is_fifo()

Возвращает True, если путь указывает на FIFO (или символическую ссылку, указывающую на FIFO), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.is_block_device()

Возвращает True, если путь указывает на блочное устройство (или символическую ссылку, указывающую на блочное устройство), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.is_char_device()

Возвращает True, если путь указывает на символьное устройство (или символическую ссылку, указывающую на символьное устройство), и False, если указывает на файл другого типа.

False также возвращается, если путь не существует или является битой символической ссылкой; другие ошибки (например, ошибки разрешений) пробрасываются.

Path.iterdir()

Если путь указывает на каталог, возвращает объекты пути для его содержимого:

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

Аналогично Path.chmod(), но если путь указывает на символическую ссылку, изменяется режим символической ссылки, а не её цели.

Path.lstat()

Аналогично Path.stat(), но если путь указывает на символическую ссылку, возвращается информация о символической ссылке, а не о её цели.

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

Создаёт новый каталог по указанному пути. Если задан параметр mode, он комбинируется со значением umask процесса для определения режима файла и флагов доступа. Если путь уже существует, возбуждается FileExistsError.

Если parents истинно, все отсутствующие родительские каталоги этого пути создаются по необходимости; они создаются с правами по умолчанию, без учёта mode (как команда POSIX mkdir -p).

Если parents ложно (значение по умолчанию), отсутствие родительского каталога приводит к возбуждению FileNotFoundError.

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

Возвращает имя пользователя, владеющего файлом. Исключение KeyError возбуждается, если uid файла не найден в системной базе данных.

Path.rename(target)

Переименовывает этот файл или каталог в указанный target. target может быть строкой или другим объектом пути:

>>> p = Path('foo')
>>> p.open('w').write('some text')
9
>>> target = Path('bar')
>>> p.rename(target)
>>> target.open().read()
'some text'
Path.replace(target)

Переименовывает этот файл или каталог в указанный target. Если target указывает на существующий файл или каталог, он будет безусловно заменён.

Path.resolve()

Делает путь абсолютным, разрешая все символические ссылки. Возвращается новый объект пути:

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

Компоненты ”..” также удаляются (это единственный способ сделать это):

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

Если путь не существует, возбуждается FileNotFoundError. Если в процессе разрешения пути обнаружен бесконечный цикл, возбуждается RuntimeError.

Path.rglob(pattern)

Это аналогично вызову glob() с добавлением «**» перед указанным pattern:

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

Удаляет этот каталог. Каталог должен быть пустым.

Делает этот путь символической ссылкой на target. В Windows target_is_directory должно быть истинным (по умолчанию False), если целью ссылки является каталог. В POSIX значение 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().

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

Создаёт файл по указанному пути. Если задан mode, он комбинируется со значением umask процесса для определения режима файла и флагов доступа. Если файл уже существует, функция выполняется успешно, если exist_ok истинно (время модификации файла обновляется до текущего), в противном случае возбуждается FileExistsError.

Удаляет этот файл или символическую ссылку. Если путь указывает на каталог, используйте Path.rmdir().