2009-05-27 256 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, '../')