Python 中的相对路径[重复]

2024-12-05 08:38:00
admin
原创
135
摘要:问题描述:我正在为工作构建一个简单的辅助脚本,它将把代码库中的几个模板文件复制到当前目录。但是,我没有存储模板的目录的绝对路径。我确实有一个来自脚本的相对路径,但是当我调用脚本时,它会将其视为相对于当前工作目录的路径。有没有办法指定这个相对 URL 来自脚本的位置?解决方案 1:在包含脚本的文件中,您需要执行...

问题描述:

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


解决方案 1:

在包含脚本的文件中,您需要执行如下操作:

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

解决方案 2:

现在已经是 2018 年了,Python 也已经进化很久__future__了。那么,何不利用 Python 3.4 的强大功能来完成pathlib任务,而不是苦苦挣扎于osos.path、、 等呢?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)

解决方案 3:

正如接受的答案中提到的

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

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

解决方案 4:

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

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

解决方案 5:

考虑我的代码:

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)

解决方案 6:

参见sys.path
在程序启动时初始化,此列表的第一项 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'

解决方案 7:

而不是使用

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

解决方案 8:

根据其他人的建议和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,我们项目根目录的路径可能会改变(因此我们需要改变部分parents[4])。

我认为我找到了一个基于相同想法的更好的解决方案。我们将使用一个文件paths.py来存储项目的根目录,该文件将保留在与根目录相同的位置。

Tests
├── data
│  └── users.csv
└── src
   ├── long
   │  └── module
   │     └── subdir
   │        └── some_script.py
   ├── main.py
   └── paths.py

Wherepaths.py的唯一责任是提供PROJECT_ROOT

from pathlib import Path

PROJECT_ROOT = Path(__file__).parents[1]

现在所有脚本都可以用来paths.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()

解决方案 9:

最重要的命令摘要

>>> 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 应该类似。

解决方案 10:

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

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

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

下面的例子可以让你正确理解上述概念

假设我有一个文件input_file_list.txt,其中包含我的 python 脚本要处理的输入文件列表。

D:\conc\输入1.dic

D:\conc\输入2.dic

D:\Copyioconc\输入文件列表.txt

如果你看到上面的文件夹结构,input_file_list.txt存在于Copyofconc文件夹中,而要由 python 脚本处理的文件存在于conc文件夹中

但是文件input_file_list.txt的内容如下所示:

..\conc\输入1.dic

..\conc\输入2.dic

我的 python 脚本位于D:盘。

并且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.dicinput2.dic,我将读取行“..\conc\input1.dic”,然后使用命令

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

因此input1_path应为“D:\conc\input1.dic”

解决方案 11:

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

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

即使在模块中这也将起作用。

解决方案 12:

对我有用的另一种方法:

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

解决方案 13:

一个简单的解决方案是

import os
os.chdir(os.path.dirname(__file__))

解决方案 14:

例子


这是一个在 Python ‘3.9.5’ 中测试的示例:

您的当前目录:'c:project1code'

并且您想要访问以下文件夹:'c:project1dataset rain'

那么您可以使用以下地址访问该文件夹:'../dataset/train/'

参考


如果您想了解更多信息path in Python,请阅读:

  • PEP - 355

  • PEP - 519

解决方案 15:

以下是我的总结:

首先,定义名为 的工具函数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

解决方案 16:

对我有用的是使用sys.path.insert。然后我指定我需要去的目录。例如,我只需要上移一个目录。

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

解决方案 17:

我认为要在所有系统上使用“ntpath”而不是“os.path”。目前,它适用于 Windows、Linux 和 Mac OSX。

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

解决方案 18:

C:UsersxyzmyFolderC:Usersxyz estdata:

import os
working_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
# C:UsersxyzmyFolder
print(working_dir)
updated_working_dir = os.path.join(os.path.realpath(working_dir + '/../'), 'testdata')
# C:Usersxyz    estdata
print(updated_working_dir)

输出

C:UsersxyzmyFolder
C:Usersxyz    estdata

解决方案 19:

假设当前目录名为“Helper”,上级目录名为“Workshop”,模板文件位于\Workshop\Templates,那么在Python中的相对路径为“..\Templates”。

解决方案 20:

这是一种向系统路径集添加相对路径的简单方法。例如,当目标目录比'/../'工作目录高一级(因此)时,通常会出现这种情况:

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 v.1916 64 位 (AMD64)]

解决方案 21:

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

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

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

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

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用