Python中的相对路径

Python中的相对路径,python,relative-path,path,Python,Relative Path,Path,我正在为工作构建一个简单的助手脚本,它将代码库中的两个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我确实有一个来自脚本的相对路径,但当我调用脚本时,它将其视为相对于当前工作目录的路径。是否有方法指定此相对url来自脚本的位置?请参阅 当程序启动时初始化时,此列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录 将此路径用作您要从中删除的根文件夹 在包含脚本的文件中,您希望执行以下操作: import os dirname = os.path.dirname(__f

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

请参阅 当程序启动时初始化时,此列表的第一项路径[0]是包含用于调用Python解释器的脚本的目录

将此路径用作您要从中删除的根文件夹


在包含脚本的文件中,您希望执行以下操作:

import os
dirname = os.path.dirname(__file__)
filename = os.path.join(dirname, 'relative/path/to/file/you/want')
这将为您提供要查找的文件的绝对路径。请注意,如果您使用的是setuptools,那么您可能应该使用它

更新:我正在回复此处的注释,以便粘贴代码示例。:-)


我认为
\uuuu文件\uuuu
并非总是可用(例如,当您直接运行文件而不是导入文件时),我的想法是否正确

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

然而,我知道C扩展名上的
\uuuu file\uuu
有一些怪癖。例如,我可以在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计算机上引发了一个异常。

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


您好,首先您应该了解函数os.path.abspath(path)os.path.relpath(path)

简而言之,os.path.abspath(path)相对路径转换为绝对路径。如果提供的路径本身是绝对路径,则函数返回相同的路径

类似地,os.path.relpath(path)绝对路径转换为相对路径。如果提供的路径本身是相对路径,则函数返回相同的路径

下面的示例可以让您正确理解上述概念

假设我有一个文件input\u file\u list.txt,其中包含python脚本要处理的输入文件列表

D:\conc\input1.dic

D:\conc\input2.dic

D:\Copyioconc\input\u file\u list.txt

如果您看到上面的文件夹结构,input\u file\u list.txt存在于copyofcnc文件夹中,并且python脚本要处理的文件存在于conc文件夹中

但是文件input\u file\u list.txt的内容如下所示:

..\conc\input1.dic

..\conc\input2.dic

我的python脚本出现在D:drive中

input\u file\u list.txt文件中提供的相对路径是相对于input\u file\u list.txt文件的路径

因此,当python脚本执行当前工作目录时(使用os.getcwd()获取路径)

由于我的相对路径是相对于输入文件\u list.txt,即“D:\Copyofconc”,因此我必须将当前工作目录更改为“D:\Copyofconc”

因此我必须使用os.chdir('D:\copyofcon'),因此当前的工作目录应该是“D:\copyofcon”

现在要获取文件input1.dicinput2.dic,我将阅读“.\conc\input1.dic”行,然后使用命令

input1\u path=os.path.abspath('..\conc\input1.dic')(将相对路径更改为绝对路径。由于当前工作目录为“D:\Copyofconc”,因此应相对于“D:\Copyofconc”访问文件“\conc\input1.dic”)


因此,input1\u路径应为“D:\conc\input1.dic”

我不确定这是否适用于某些旧版本,但我相信Python 3.3具有本机相对路径支持

例如,以下代码应在与python脚本相同的文件夹中创建一个文本文件:

open("text_file_name.txt", "w+t")

(请注意,如果是相对路径,则开头不应该有正斜杠或反斜杠)

一个对我有用的替代方法:

this_dir = os.path.dirname(__file__) 
filename = os.path.realpath("{0}/relative/file.path".format(this_dir))
以我的代码为例:

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')
如公认的答案所示,使用以下方法更为可靠:

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 _将返回从中加载模块的文件(如果从文件加载),因此如果从其他地方调用包含脚本的文件,则返回的目录将不正确


这些答案提供了更多细节:并且

此代码将返回主脚本的绝对路径

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

即使在一个模块中,这也会起作用。

如公认答案中所述

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

接受的答案在某些情况下可能会产生误导,有关详细信息,请参阅链接

对我有效的方法是使用
sys.path.insert
。然后我指定了我需要去的目录。例如,我只需要进入一个目录

import sys
sys.path.insert(0, '../')

现在是2018年,Python很早以前就已经发展到了未来。那么,使用Python3.4带来的惊人功能来完成任务,而不是在
os
os.path
glob
shutil
等方面苦苦挣扎,怎么样

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

  • mod_path
    :这是简单助手脚本的路径
  • src_path
    :包含两个等待复制的模板文件
  • cwdimport 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')
    
    import sys
    sys.path.insert(0, '../')
    
    # 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()
    
    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)
    
    >>> 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'
    
    import ntpath
    import os
    dirname = ntpath.dirname(__file__)
    filename = os.path.join(dirname, 'relative/path/to/file/you/want')
    
    import os
    os.chdir(os.path.dirname(__file__))
    
    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