Найти путь в Windows относительно другого - PullRequest
2 голосов
/ 31 октября 2009

Эта проблема должна быть легкой, но я пока не смог ее решить.

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

Здесь в качестве попытки реализации, в комплекте с несколькими 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, эта реализация завершается неудачно, когда в начале указывается буква диска, а цель указана относительно корня диска.

Это поднимает несколько вопросов

  1. Является ли это поведение ограничением os.path.join? Другими словами, должен ли os.path.join ('d: \ foo', '\ bar') преобразовываться в 'd: \ bar'? Как пользователь Windows, я склонен так думать, но мне неприятно думать, что зрелая функция, такая как path.join, нуждается в изменении для обработки этого варианта использования.
  2. Есть ли пример существующего преобразователя целевого пути, такого как findpath, который будет работать во всех этих тестовых случаях?
  3. Если «нет» на поставленные выше вопросы, как бы вы реализовали это желаемое поведение?

1 Ответ

2 голосов
/ 31 октября 2009

Я согласен с вами: это похоже на недостаток в os.path.join. Похоже, вы должны иметь дело с дисками отдельно. Этот код проходит все ваши тесты:

def findpath(target, start=os.path.curdir):
    sdrive, start = os.path.splitdrive(start)
    tdrive, target = os.path.splitdrive(target)
    rdrive = tdrive or sdrive
    return os.path.normpath(os.path.join(rdrive, os.path.join(start, target)))

(и да, мне пришлось вложить два файла os.path.join, чтобы он заработал ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...