Pathlib «нормализует» пути UNC с помощью $

В Python3.8 я пытаюсь использовать pathlib для объединения строки с путем UNC, который находится на диске C удаленного компьютера.
Это странная непоследовательность.
Например:

>>> remote = Path("\\\\remote\\", "C$\\Some\\Path")
>>> remote
WindowsPath('//remote//C$/Some/Path')

>>> remote2 = Path(remote, "More")
>>> remote2
WindowsPath('/remote/C$/Some/Path/More')

Заметили, как начальный // превращается в /?
Однако поместите начальный путь в одну строку, и все в порядке:

>>> remote = Path("\\\\remote\\C$\\Some\\Path")
>>> remote
WindowsPath('//remote/C$/Some/Path')

>>> remote2 = Path(remote, "more")
>>> remote2
WindowsPath('//remote/C$/Some/Path/more')

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


person Elad Avron    schedule 05.02.2020    source источник
comment
Не могли бы вы напечатать обе части remote._parts (и, возможно, обе части remote2s _parts)? Там также есть ._root и ._drive. Может быть, это что-то о том, как интерпретируются части и как это влияет на разрушение косой черты.   -  person h4z3    schedule 05.02.2020


Ответы (1)


tldr: вы должны указать весь общий ресурс UNC (\\\\host\\share) как единое целое, pathlib имеет особую обработку путей UNC, но ему нужен именно этот префикс, чтобы распознавать путь как UNC. Вы не можете использовать средства pathlib для раздельного управления хостом и общим ресурсом, это делает pathlib невозможным.

Конструктор Path нормализует (дедуплицирует) разделители пути:

>>> PPP('///foo//bar////qux')
PurePosixPath('/foo/bar/qux')
>>> PWP('///foo//bar////qux')
PureWindowsPath('/foo/bar/qux')

PureWindowsPath имеет особый случай для путей, распознаваемых как UNC, то есть //host/share..., который позволяет избежать свертывания начальных разделителей.

Однако ваша первоначальная конкатенация помещает его в странный фанк, потому что он создает путь формы //host//share..., затем путь преобразуется обратно в строку при передаче конструктору, после чего он не соответствует UNC больше, и все разделители свернуты:

>>> PWP("\\\\remote\\", "C$\\Some\\Path")
PureWindowsPath('//remote//C$/Some/Path')
>>> str(PWP("\\\\remote\\", "C$\\Some\\Path"))
'\\\\remote\\\\C$\\Some\\Path'
>>> PWP(str(PWP("\\\\remote\\", "C$\\Some\\Path")))
PureWindowsPath('/remote/C$/Some/Path')

проблема, по-видимому, заключается именно в наличии завершающего разделителя на пути, похожем на UNC, я не знаю, является ли это ошибкой или соответствует какому-то другому особому случаю в стиле UNC (но не UNC):

>>> PWP("//remote")
PureWindowsPath('/remote')
>>> PWP("//remote/")
PureWindowsPath('//remote//') # this one is weird, the trailing separator gets doubled which breaks everything
>>> PWP("//remote/foo")
PureWindowsPath('//remote/foo/')
>>> PWP("//remote//foo")
PureWindowsPath('/remote/foo')

Такое поведение на самом деле не кажется задокументированным, в документе pathlib особо отмечается, что он сворачивает разделители путей, и есть несколько примеров UNC, которые показывают, что это не так, но я действительно не знаю, что именно должно происходить. В любом случае кажется, что UNC-пути обрабатываются правильно только в том случае, если первые два сегмента хранятся как единый «дисковый» блок, а общий путь считается диском специально задокументирован.

Обратите внимание: использование joinpath / /, похоже, не вызывает повторную нормализацию, ваш путь остается неправильным (поскольку второй путь между хостом и общим ресурсом остается удвоенным), но он не полностью сворачивается.

person Masklinn    schedule 05.02.2020