2009-10-31 55 views
2

在Windows中的相對路徑這個問題應該是一個沒有腦子,但我還沒有能夠打釘。查找另一個

我需要一個函數,它有兩個參數,每一個文件路徑,相對或絕對的,並返回一個文件路徑是第一路徑(目標)相對於所述第二路徑得到解決(開始)。解決的路徑可能是相對於當前目錄或可能是絕對的(我不在乎)。

這裏作爲一個嘗試實現,完全與幾個文檔的測試,即行使某些示例使用情況下(並說明它失敗)。 A runnable script is also available on my source code repository,但它可能會改變。如果未提供任何參數,則可運行腳本將運行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)) 

正如你可以從文檔測試註釋中看到,當啓動指定驅動器號和目標是相對於驅動器的根本實施失敗。

這帶來了幾個問題

  1. 這種行爲os.path.join的限制?換句話說,如果os.path.join('d:\ foo','\ bar')解析爲'd:\ bar'?作爲Windows用戶,我傾向於這樣認爲,但我討厭認爲像path.join這樣的成熟函數需要改變來處理這種用例。
  2. 有諸如findpath將在所有這些測試用例工作現有的目標路徑分解的例子嗎?
  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))) 

(是的,我只好窩2 os.path.join的得到它的工作...)

相關問題