2009-05-27 586 views
128

我正在構建一個簡單的幫助腳本,用於將我們的代碼庫中的幾個模板文件複製到當前目錄。但是,我不具有存儲模板的目錄的絕對路徑。我確實有一個來自腳本的相對路徑,但是當我調用腳本時,它會將它視爲相對於當前工作目錄的路徑。有沒有一種方法可以指定這個相對的URL來自腳本的位置呢?Python中的相對路徑

+0

類似的問題: https://stackoverflow.com/questions/51520/how-to-get-an-absolute-file-path-in-python https://stackoverflow.com/questions/ 7165749 /在Python中的相對位置打開文件 https://stackoverflow.com/questions/3561691/python-syntaxerror-eol-while-scanning-string-literal – Raj 2017-10-12 21:24:13

回答

164

在具有腳本文件,你想要做這樣的事情的根文件夾:

import os 
dirname = os.path.dirname(__file__) 
filename = os.path.join(dirname, '/relative/path/to/file/you/want') 

這會給你的您正在尋找的文件的絕對路徑。請注意,如果您使用setuptools,則應該使用它的package resources API

UPDATE:我回應這裏的評論,所以我可以粘貼一個代碼示例。 :-)

我正確地認爲__file__並不總是可用的(例如,當您直接運行文件而不是導入它時)?

我假設你指的是__main__腳本,當你提到直接運行文件時。如果是這樣,不會出現在我的系統(蟒蛇2.5.1 OS X 10.5.7)的情況下:

#foo.py 
import os 
print os.getcwd() 
print __file__ 

#in the interactive interpreter 
>>> import foo 
/Users/jason 
foo.py 

#and finally, at the shell: 
~ % python foo.py 
/Users/jason 
foo.py 

不過,我知道有一些怪癖與__file__上的C擴展。例如,我可以在我的Mac上執行此操作:

>>> import collections #note that collections is a C extension in Python 2.5 
>>> collections.__file__ 
'/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib- 
dynload/collections.so' 

但是,這在我的Windows計算機上引發了一個例外。

+1

我正確地認爲__file__並不總是可用的(例如,當您直接運行文件而不是導入文件時)? – 2009-05-28 12:43:25

+0

@Stephen Edmonds我使用它來運行一個文件,而不是導入,它效果很好。 – baudtack 2009-06-04 03:37:39

+13

請注意,您應該在任何地方使用os.path.join以實現可移植性:'filename = os.path.join(dir,'relative','path','to','file','you','want')' – ford 2014-02-06 17:51:14

10

請參閱sys.path 在程序啓動時初始化,此列表中的第一項path [0]是包含用於調用Python解釋器的腳本的目錄。

使用此路徑,從中apply your relative path

>>> import sys 
>>> import os.path 
>>> sys.path[0] 
'C:\\Python25\\Lib\\idlelib' 
>>> os.path.relpath(sys.path[0], "path_to_libs") # if you have python 2.6 
>>> os.path.join(sys.path[0], "path_to_libs") 
'C:\\Python25\\Lib\\idlelib\\path_to_libs' 
+3

這不一定是真的。通常sys.path [0]是一個空字符串或點,它是當前目錄的相對路徑。如果您想要當前目錄,請使用os.getcwd。 – 2009-05-27 21:54:04

+0

原來的海報評論說,當前的工作目錄是以相對路徑爲基礎的錯誤地方。你說這個系統是正確的。路徑[0]並不總是有效的。 – 2009-05-28 00:56:08

43

你需要os.path.realpath(以下樣品添加父目錄到您的路徑)

import sys,os 
sys.path.append(os.path.realpath('..')) 
+2

'os.path.dirname(__ file __)'給了我一個空字符串。這工作完美。 – 2014-02-21 10:51:17

+0

這似乎給出了腳本運行的目錄的父目錄,而不是腳本的位置。 – Coquelicot 2017-07-17 03:50:49

+0

@ user98762它在Windows上如何工作? – zviad 2018-01-05 11:18:22

1

喜首先你應該瞭解的功能os.path.abspath則(路徑)os.path.relpath (路徑)

總之os.path.abspath則(路徑)使得相對路徑絕對路徑。如果提供的路徑本身是絕對路徑,則該函數返回相同的路徑。

類似os.path.relpath(路徑)使得絕對路徑相對路徑。如果提供的路徑本身是一個相對路徑,那麼函數返回相同的路徑。

下面的例子可以讓你正確理解上述概念:

假設我有一個文件input_file_list.txt其中包含由我的Python腳本處理的輸入文件列表。

d:\濃度\ input1.dic

d:\濃度\ input2.dic

d:\ Copyioconc \ input_file_list.txt

如果你看到上面的文件夾結構,的input_file_list。 TXT存在於Copyofconc文件夾和文件,以由Python腳本中文件夾被處理的本

但是,如下圖所示的文件的input_file_list.txt內容:

.. \濃度\ input1.dic

.. \濃度\ input2.dic

我的Python腳本是目前在D:驅動器。

而在input_file_list.txt文件中提供的相對路徑是相對於input_file_list.txt文件的路徑。

所以當python腳本應執行當前的工作目錄(使用os.getcwd()得到的路徑)

由於我的相對路徑是相對於input_file_list.txt,那就是「d :\ Copyofconc「,我必須將當前工作目錄更改爲」D:\ Copyofconc「

所以我必須使用os.chdir( 'd:\ Copyofconc'),所以當前的工作目錄應「d:\ Copyofconc」

現在需要的檔案input1.dicinput2.dic,我會讀行 「.. \濃度\ input1.dic」,那麼應使用命令

input1_path = OS。 path.abspath('.. \ conc \ input1.dic')(將相對路徑改爲絕對路徑,當前工作目錄爲「D:\ Copyofconc」,文件「。\ conc \ input1.dic」爲相對於「D:\ Copyofconc」被訪問)

因此input1_path應該是「D:\ conc \ input1.dic」

-1

我不確定這是否適用於某些舊版本,但我相信Python 3.3具有本機相對路徑支持。

例如下面的代碼應在同一文件夾中的python腳本創建一個文本文件:

open("text_file_name.txt", "w+t") 

(注意,不應該是一個正向或反斜線開頭,如果它是一個相對路徑)

1

這對我的作品的另一種:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir)) 
7

考慮我的代碼:

import os 


def readFile(filename): 
    filehandle = open(filename) 
    print filehandle.read() 
    filehandle.close() 



fileDir = os.path.dirname(os.path.realpath('__file__')) 
print fileDir 

#For accessing the file in the same folder 
filename = "same.txt" 
readFile(filename) 

#For accessing the file in a folder contained in the current folder 
filename = os.path.join(fileDir, 'Folder1.1/same.txt') 
readFile(filename) 

#For accessing the file in the parent folder of the current folder 
filename = os.path.join(fileDir, '../same.txt') 
readFile(filename) 

#For accessing the file inside a sibling folder. 
filename = os.path.join(fileDir, '../Folder2/same.txt') 
filename = os.path.abspath(os.path.realpath(filename)) 
print filename 
readFile(filename) 
3

而不是使用

import os 
dirname = os.path.dirname(__file__) 
filename = os.path.join(dirname, '/relative/path/to/file/you/want') 

在接受答案的,那將是更強大的使用方法:

import inspect 
import os 
dirname = os.path.dirname(os.path.abspath(inspect.stack()[0][1])) 
filename = os.path.join(dirname, '/relative/path/to/file/you/want') 

,因爲使用__file__將返回從該模塊被加載的文件,如果它是從文件加載的,那麼如果帶有該腳本的文件是從別處調用的,那麼返回的目錄將不正確。

這些答案給更多詳細信息:https://stackoverflow.com/a/31867043/5542253https://stackoverflow.com/a/50502/5542253

2

此代碼將返回到主腳本的絕對路徑。

import os 
def whereAmI(): 
    return os.path.dirname(os.path.realpath(__import__("__main__").__file__)) 

即使在一個模塊中,這也可以工作。

29

作爲公認的答案中提到

import os 
dir = os.path.dirname(__file__) 
filename = os.path.join(dir, '/relative/path/to/file/you/want') 

我只想補充一點,

後者字符串不能用反斜槓開頭,事實上沒有字符串 應該包括一個反斜槓

它應該是類似於

import os 
dir = os.path.dirname(__file__) 
filename = os.path.join(dir, 'relative','path','to','file','you','want') 

接受的答案可能會誤導在一些情況下,請參閱this鏈接細節

+3

是的,使用'os.path.join'更好,因爲它將它們與OS特定的分隔符結合在一起。 – 2016-09-04 09:16:24

+0

''/ relative/path ...''不是相對路徑。那是故意的嗎? – steveire 2018-02-13 12:24:08

1

什麼對我來說是使用sys.path.insert工作。然後我指定了我需要去的目錄。例如,我只需要上一個目錄。

import sys 
sys.path.insert(0, '../')