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


当前回答

考虑一下我的代码:

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)

其他回答

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

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机器上引发一个异常。

最重要命令的摘要

>>> import os
>>> os.path.join('/home/user/tmp', 'subfolder')
'/home/user/tmp/subfolder'
>>> os.path.normpath('/home/user/tmp/../test/..')
'/home/user'
>>> os.path.relpath('/home/user/tmp', '/home/user')
'tmp'
>>> os.path.isabs('/home/user/tmp')
True
>>> os.path.isabs('/tmp')
True
>>> os.path.isabs('tmp')
False
>>> os.path.isabs('./../tmp')
False
>>> os.path.realpath('/home/user/tmp/../test/..') # follows symbolic links
'/home/user'

详细的描述可以在文档中找到。 这些是linux路径。Windows的工作原理与此类似。

另一个适合我的选择是:

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

正如在已接受的答案中提到的

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')

接受的答案在某些情况下可能会误导,详情请参阅此链接

从C:\Users\xyz\myFolder到C:\Users\xyz\testdata:

import os
working_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# C:\Users\xyz\myFolder
print(working_dir)
updated_working_dir = os.path.join(os.path.realpath(working_dir + '/../'), 'testdata')
# C:\Users\xyz\testdata
print(updated_working_dir)

输出

C:\Users\xyz\myFolder
C:\Users\xyz\testdata