Эта проблема должна быть легкой, но я пока не смог ее решить.
Мне нужна функция, которая принимает два параметра, каждый путь к файлу, относительный или абсолютный, и возвращает путь к файлу, который является первым путем (целью), разрешенным относительно второго пути (начала). Разрешенный путь может быть относительно текущего каталога или может быть абсолютным (мне все равно).
Здесь в качестве попытки реализации, в комплекте с несколькими doc-тестами, в которой используются некоторые примеры использования (и демонстрируется, где он терпит неудачу). Запускаемый сценарий также доступен в моем репозитории исходного кода , но он может измениться. Исполняемый сценарий запустит doctest, если параметры не указаны, или передаст один или два параметра в findpath, если он указан.
def findpath(target, start=os.path.curdir):
r"""
Find a path from start to target where target is relative to start.
>>> orig_wd = os.getcwd()
>>> os.chdir('c:\\windows') # so we know what the working directory is
>>> findpath('d:\\')
'd:\\'
>>> findpath('d:\\', 'c:\\windows')
'd:\\'
>>> findpath('\\bar', 'd:\\')
'd:\\bar'
>>> findpath('\\bar', 'd:\\foo') # fails with '\\bar'
'd:\\bar'
>>> findpath('bar', 'd:\\foo')
'd:\\foo\\bar'
>>> findpath('bar\\baz', 'd:\\foo')
'd:\\foo\\bar\\baz'
>>> findpath('\\baz', 'd:\\foo\\bar') # fails with '\\baz'
'd:\\baz'
Since we're on the C drive, findpath may be allowed to return
relative paths for targets on the same drive. I use abspath to
confirm that the ultimate target is what we expect.
>>> os.path.abspath(findpath('\\bar'))
'c:\\bar'
>>> os.path.abspath(findpath('bar'))
'c:\\windows\\bar'
>>> findpath('..', 'd:\\foo\\bar')
'd:\\foo'
>>> findpath('..\\bar', 'd:\\foo')
'd:\\bar'
The parent of the root directory is the root directory.
>>> findpath('..', 'd:\\')
'd:\\'
restore the original working directory
>>> os.chdir(orig_wd)
"""
return os.path.normpath(os.path.join(start, target))
Как видно из комментариев в doctest, эта реализация завершается неудачно, когда в начале указывается буква диска, а цель указана относительно корня диска.
Это поднимает несколько вопросов
- Является ли это поведение ограничением os.path.join? Другими словами, должен ли os.path.join ('d: \ foo', '\ bar') преобразовываться в 'd: \ bar'? Как пользователь Windows, я склонен так думать, но мне неприятно думать, что зрелая функция, такая как path.join, нуждается в изменении для обработки этого варианта использования.
- Есть ли пример существующего преобразователя целевого пути, такого как findpath, который будет работать во всех этих тестовых случаях?
- Если «нет» на поставленные выше вопросы, как бы вы реализовали это желаемое поведение?