2009-10-31 3 views
2

Эта проблема должна быть без проблем, но я еще не смог ее прибить.Найти путь в Windows относительно другого

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

Здесь, как попытка реализации, в комплекте с несколькими тестами doc, которые выполняют некоторые примеры использования примеров (и демонстрирует, где он не работает). A runnable script is also available on my source code repository, но это может измениться. Сценарий runnable будет запускать 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. Есть ли пример существующего целевого распознавателя пути, такого как путь поиска, который будет работать во всех этих тестовых случаях?
  3. Если «нет» на вышеуказанные вопросы, как бы вы реализовали это желаемое поведение?

ответ

2

Я согласен с вами: это похоже на недостаток в 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, чтобы заставить его работать ...)