我正在构建一个简单的助手脚本,用于将代码库中的两个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我有一个相对路径从脚本,但当我调用脚本,它把它作为一个相对于当前工作目录的路径。是否有一种方法来指定这个相对url是来自脚本的位置?
当前回答
而不是使用
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
其他回答
看到sys.path 在程序启动时初始化后,该列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录。
使用此路径作为根文件夹,从中应用相对路径
>>> 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'
正如在已接受的答案中提到的
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')
接受的答案在某些情况下可能会误导,详情请参阅此链接
例子
下面是一个用Python '3.9.5 '测试的例子:
您的当前目录:'c:\project1\code\' 你想要访问以下文件夹:'c:\project1\dataset\train\'。 然后您可以使用以下地址访问该文件夹:“../dataset/train/”
参考文献
如果你想了解更多关于Python中路径的信息,请阅读以下内容:
Pep - 355 Pep - 519
Hi首先你需要理解os。path。abspath(path)和os。path。relpath(path)
简而言之,os.path.abspath(path)将相对路径转换为绝对路径。如果提供的路径本身是一个绝对路径,那么函数返回相同的路径。
类似地,os.path.relpath(path)将绝对路径转换为相对路径。如果提供的路径本身是相对路径,则函数返回相同的路径。
下面的例子可以让你正确理解上面的概念:
假设我有一个文件input_file_list.txt,其中包含要由我的python脚本处理的输入文件列表。
D: \ \ input1.dic浓缩
D: \ \ input2.dic浓缩
D: \ Copyioconc input_file_list。txt
如果你看到上面的文件夹结构,input_file_list.txt在Copyofconc文件夹中,python脚本要处理的文件在conc文件夹中
但是input_file_list.txt文件的内容如下所示:
. . \ \ input1.dic浓缩
. . \ \ input2.dic浓缩
我的python脚本在D: drive中。
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。Dic和input2。Dic,我将读取“..\conc\input1”这行。然后使用命令
Input1_path = os.path.abspath('..\conc\input1.dic')(将相对路径更改为绝对路径。这里作为当前的工作目录是“D:\Copyofconc”,文件“.\conc\input1.”相对于"D:\Copyofconc")
所以input1_path应该是“D:\conc\input1.dic”
根据其他建议和pathlib文档,一个简单(但不理想)的解决方案如下(假设我们需要引用的文件是Test/data/users.csv):
# Current file location: Tests/src/long/module/subdir/some_script.py
from pathlib import Path
# back to Tests/
PROJECT_ROOT = Path(__file__).parents[4]
# then down to Test/data/users.csv
CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'
with CSV_USERS_PATH.open() as users:
print(users.read())
这是可行的,但看起来有点奇怪,因为如果您移动some_script.py,到项目根目录的路径可能会改变(因此我们需要更改父目录[4]部分)。
我想我找到了一个更好的解决方案,基于同样的想法。 我们将使用path .py文件来存储项目的根目录,与根目录相比,这个文件将保持在相同的位置。
Tests
├── data
│ └── users.csv
└── src
├── long
│ └── module
│ └── subdir
│ └── some_script.py
├── main.py
└── paths.py
path .py的唯一职责是提供PROJECT_ROOT:
from pathlib import Path
PROJECT_ROOT = Path(__file__).parents[1]
所有脚本现在都可以使用路径。PROJECT_ROOT表示从项目根开始的绝对路径。例如,在src/long/module/subdir/some_script.py中,我们可以有:
from paths import PROJECT_ROOT
CSV_USERS_PATH = PROJECT_ROOT / 'data' / 'users.csv'
def hello():
with CSV_USERS_PATH.open() as f:
print(f.read())
一切都如你所料:
~/Tests/src/$ python main.py
/Users/cglacet/Tests/data/users.csv
hello, user
~/Tests/$ python src/main.py
/Users/cglacet/Tests/data/users.csv
hello, user
main.py脚本就是:
from long.module.subdir import some_script
some_script.hello()