我正在构建一个简单的助手脚本,用于将代码库中的两个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我有一个相对路径从脚本,但当我调用脚本,它把它作为一个相对于当前工作目录的路径。是否有一种方法来指定这个相对url是来自脚本的位置?


当前回答

以下是我的总结:

首先,定义名为relpath的工具函数,它将当前文件的相对路径转换为cwd的相对路径

import os
relpath = lambda p: os.path.normpath(os.path.join(os.path.dirname(__file__), p))

然后我们使用它来包装相对于当前文件的路径

path1 = relpath('../src/main.py')

你也可以调用sys.path.append()来导入相对于当前文件位置的文件

sys.path.append(relpath('..')) # so that you can import from upper dir

完整的示例代码:https://gist.github.com/luochen1990/9b1ffa30f5c4a721dab5991e040e3eb1

其他回答

而不是使用

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/5542253和https://stackoverflow.com/a/50502/5542253

这段代码将返回主脚本的绝对路径。

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

这甚至可以在一个模块中工作。

在有脚本的文件中,你想做这样的事情:

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

这将为您提供您正在寻找的文件的绝对路径。注意,如果你正在使用setuptools,你可能应该使用它的包资源API。

更新:我在这里响应一个注释,所以我可以粘贴一个代码示例。: -)

我是否正确地认为__file__并不总是可用的(例如,当你直接运行文件而不是导入它)?

当你提到直接运行文件时,我假设你指的是__main__脚本。如果是这样,在我的系统上似乎不是这样(OS X 10.5.7上的python 2.5.1):

#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

然而,我确实知道C扩展名上的__file__有一些怪癖。例如,我可以在我的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机器上引发一个异常。

以下是我的总结:

首先,定义名为relpath的工具函数,它将当前文件的相对路径转换为cwd的相对路径

import os
relpath = lambda p: os.path.normpath(os.path.join(os.path.dirname(__file__), p))

然后我们使用它来包装相对于当前文件的路径

path1 = relpath('../src/main.py')

你也可以调用sys.path.append()来导入相对于当前文件位置的文件

sys.path.append(relpath('..')) # so that you can import from upper dir

完整的示例代码:https://gist.github.com/luochen1990/9b1ffa30f5c4a721dab5991e040e3eb1

您需要os.path.realpath(下面的示例将父目录添加到您的路径中)

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