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


当前回答

这是向系统路径集添加相对路径的简单方法。例如,对于目标目录比工作目录高一级(例如'/../')的常见情况:

import os
import sys
workingDir = os.getcwd()
targetDir = os.path.join(os.path.relpath(workingDir + '/../'),'target_directory')
sys.path.insert(0,targetDir)

对该解决方案进行了测试:

Python 3.9.6 |由conda-forge |打包(默认,2021年7月11日, 03:37:25) [MSC .1916 64位(AMD64)]

其他回答

现在是2018年,Python很久以前就已经进化到__future__了。因此,如何使用Python 3.4附带的惊人的pathlib来完成任务,而不是在os, os中苦苦挣扎。路径,glob, shutil等。

这里有3条路径(可能重复):

Mod_path:简单帮助脚本的路径 Src_path:包含两个等待复制的模板文件。 Cwd:当前目录,这些模板文件的目的地。

问题是:我们没有src_path的完整路径,只知道它到mod_path的相对路径。

现在让我们用惊人的pathlib来解决这个问题:

# Hope you don't be imprisoned by legacy Python code :)
from pathlib import Path

# `cwd`: current directory is straightforward
cwd = Path.cwd()

# `mod_path`: According to the accepted answer and combine with future power
# if we are in the `helper_script.py`
mod_path = Path(__file__).parent
# OR if we are `import helper_script`
mod_path = Path(helper_script.__file__).parent

# `src_path`: with the future power, it's just so straightforward
relative_path_1 = 'same/parent/with/helper/script/'
relative_path_2 = '../../or/any/level/up/'
src_path_1 = (mod_path / relative_path_1).resolve()
src_path_2 = (mod_path / relative_path_2).resolve()

在未来,就这么简单。


此外,我们可以使用pathlib选择、检查和复制/移动这些模板文件:

if src_path != cwd:
    # When we have different types of files in the `src_path`
    for template_path in src_path.glob('*.ini'):
        fname = template_path.name
        target = cwd / fname
        if not target.exists():
            # This is the COPY action
            with target.open(mode='wb') as fd:
                fd.write(template_path.read_bytes())
            # If we want MOVE action, we could use:
            # template_path.replace(target)

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

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

另一个适合我的选择是:

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

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

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

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

以下是我的总结:

首先,定义名为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