在 Python 中的相对位置打开文件
Posted
技术标签:
【中文标题】在 Python 中的相对位置打开文件【英文标题】:Open file in a relative location in Python 【发布时间】:2011-11-02 04:55:28 【问题描述】:假设我的python代码在一个名为main
的目录中执行,应用程序需要访问main/2091/data.txt
。
我应该如何使用open(location)
?参数location
应该是什么?
我发现下面的简单代码可以工作..它有什么缺点吗?
file = "\2091\sample.txt"
path = os.getcwd()+file
fp = open(path, 'r+');
【问题讨论】:
您正在使用未转义的反斜杠。这是一个缺点。 几个缺点。 1)根据@orip,对路径使用正斜杠,即使在Windows上也是如此。你的字符串不起作用。或者使用像r"\2091\sample.txt"
这样的原始字符串。或者像"\\2091\\sample.txt"
一样逃避它们(但这很烦人)。另外,2)您正在使用 getcwd() ,这是您执行脚本时所在的路径。我以为你想要相对于脚本位置(但现在我想知道)。 3),始终使用os.path
函数来操作路径。你的路径加入线应该是os.path.join(os.getcwd(), file)
4) ;没有意义
为了更好的衡量... 5) 使用上下文保护来保持它的清洁并避免忘记关闭你的文件:with open(path, 'r+') as fp:
。请参阅 here 以获得对我所见过的 with
语句的最佳解释。
除了对斜线的必要注意之外,正如刚才所指出的,还有os.path.abspath
函数可以轻松获取要打开的相对路径的完整路径。最终声明如下所示:os.path.abspath('./2091/sample.txt')
【参考方案1】:
这取决于您使用的操作系统。如果您想要一个与 Windows 和 *nix 兼容的解决方案,例如:
from os import path
file_path = path.relpath("2091/data.txt")
with open(file_path) as f:
<do stuff>
应该可以正常工作。
path
模块能够为其运行的任何操作系统格式化路径。此外,只要您拥有正确的权限,python 就可以很好地处理相对路径。
编辑:
正如 kindall 在 cmets 中提到的,python 无论如何都可以在 unix 风格和 windows 风格的路径之间转换,所以更简单的代码也可以工作:
with open("2091/data/txt") as f:
<do stuff>
话虽如此,path
module 仍然有一些有用的功能。
【讨论】:
relpath()
将路径名转换为相对路径。由于它已经是相对路径,所以它什么也不做。
如果合适的话,它将把它从一个unix风格的路径转换成windows风格的路径。 os.path
模块中是否还有其他功能会是更好的选择?
Windows 已经可以使用 UNIX 样式的路径正常工作。至少基于 NT 的系列会(2000、XP、Vista、7)。无需转换。
这个答案不太正确,会引起问题。默认情况下,相对路径是相对于当前工作目录(执行脚本的路径),而不是实际的脚本位置。您需要使用__file__
。请看我的回答。
这个答案的作者是否将 os.path.relpath 与 os.path.abspath 混淆了?【参考方案2】:
Python 只是将你给它的文件名传递给操作系统,操作系统会打开它。如果您的操作系统支持像 main/2091/data.txt
这样的相对路径(提示:它支持),那么这将正常工作。
您可能会发现回答此类问题的最简单方法是尝试一下,看看会发生什么。
【讨论】:
不正确...脚本中的工作目录是您运行脚本的位置,不是脚本的位置。如果您从其他地方运行脚本(可能脚本在您的系统路径中),子目录的相对路径将不起作用。请参阅我关于如何解决此问题的答案。 @Russ - OP 的示例使用getcwd()
。我将原始描述阅读为“相对于我运行脚本的位置,无论代码位于何处”。
@orip - OP 在问题后 3 小时添加了 getcwd() 调用。没关系……继续。 :)【参考方案3】:
使用这种类型的东西,您需要注意您的实际工作目录是什么。例如,您可能不会从文件所在的目录运行脚本。在这种情况下,您不能只使用相对路径本身。
如果您确定您想要的文件位于脚本实际所在的子目录下,您可以使用__file__
来帮助您。 __file__
是您正在运行的脚本所在的完整路径。
所以你可以摆弄这样的东西:
import os
script_dir = os.path.dirname(__file__) #<-- absolute dir the script is in
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)
【讨论】:
我发现下面的简单代码可以工作..它有什么缺点吗? file="\sample.txt" path=os.getcwd()+str(loc)+file fp=open(path,'r+');
@Arash 这样做的缺点是 cwd(当前工作目录)可以是任何东西,不一定是您的脚本所在的位置。
__file__
是一个相对路径(至少在我的设置中,出于某种原因),您需要先调用os.path.abspath(__file__)
。 osx/自制 2.7
os.path.dirname(file) 在 Python 2.7 中对我不起作用。它显示NameError: name '__file__' is not defined
@Soumendra 我认为您正在控制台中尝试它。在 *.py 文件中尝试。【参考方案4】:
不确定这是否适用于任何地方。
我在 ubuntu 中使用 ipython。
如果要读取当前文件夹子目录下的文件:
/current-folder/sub-directory/data.csv
您的脚本在当前文件夹中 试试这个:
import pandas as pd
path = './sub-directory/data.csv'
pd.read_csv(path)
【讨论】:
【参考方案5】:我创建了一个帐户,以便澄清我认为在 Russ 的原始回复中发现的差异。
供参考,他原来的回答是:
import os
script_dir = os.path.dirname(__file__)
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)
这是一个很好的答案,因为它正在尝试动态创建所需文件的绝对系统路径。
Cory Mawhorter 注意到 __file__
是一个相对路径(在我的系统上也是如此)并建议使用 os.path.abspath(__file__)
。但是,os.path.abspath
返回当前脚本的绝对路径(即/path/to/dir/foobar.py
)
要使用此方法(以及我最终如何使用它),您必须从路径末尾删除脚本名称:
import os
script_path = os.path.abspath(__file__) # i.e. /path/to/dir/foobar.py
script_dir = os.path.split(script_path)[0] #i.e. /path/to/dir/
rel_path = "2091/data.txt"
abs_file_path = os.path.join(script_dir, rel_path)
生成的 abs_file_path(在本例中)变为:/path/to/dir/2091/data.txt
【讨论】:
你甚至可以结合这两种方法来获得更简单的os.path.dirname(os.path.abspath(__file__))
@LukeTaylor 实际上,这比我去年在回答中尝试自己复制 os.path.dirname
功能要好。【参考方案6】:
这段代码运行良好:
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)
【讨论】:
对我来说访问当前文件夹的父文件夹中的文件不起作用.. .. 被添加为字符串.. 在 Windows 上不起作用。文件路径正确,但 Python 状态为“找不到文件”并显示带有 \\ 分隔符的路径。 在 Ubuntu 和 python3 中,我不得不引用'__file__'
的引号,所以它变成了:fileDir = os.path.dirname(os.path.realpath(__file__))
【参考方案7】:
如果文件在您的父文件夹中,例如。 follower.txt,你可以简单地使用open('../follower.txt', 'r').read()
【讨论】:
【参考方案8】:试试这个:
from pathlib import Path
data_folder = Path("/relative/path")
file_to_open = data_folder / "file.pdf"
f = open(file_to_open)
print(f.read())
Python 3.4 引入了一个新的标准库来处理文件和路径,称为 pathlib。它对我有用!
【讨论】:
请改用with data_folder.open() as f
【参考方案9】:
我花了很多时间来发现为什么我的代码在 Windows 系统上找不到运行 Python 3 的文件。所以我加了。之前 / 一切正常:
import os
script_dir = os.path.dirname(__file__)
file_path = os.path.join(script_dir, './output03.txt')
print(file_path)
fptr = open(file_path, 'w')
【讨论】:
更好:file_path = os.path.join(script_dir, 'output03.txt')
我在 Windows 操作系统上试过,但没有成功。
有趣 - 你能打印 script_dir 吗?然后将其转换为绝对路径,如script_dir = os.path.abspath(os.path.dirname(__file__))
我会试试的,如果我成功了,我会改变答案。【参考方案10】:
代码:
import os
script_path = os.path.abspath(__file__)
path_list = script_path.split(os.sep)
script_directory = path_list[0:len(path_list)-1]
rel_path = "main/2091/data.txt"
path = "/".join(script_directory) + "/" + rel_path
说明:
导入库:
import os
使用__file__
获取当前脚本的路径:
script_path = os.path.abspath(__file__)
将脚本路径分成多个项目:
path_list = script_path.split(os.sep)
删除列表中的最后一项(实际的脚本文件):
script_directory = path_list[0:len(path_list)-1]
添加相对文件的路径:
rel_path = "main/2091/data.txt
加入列表项,并添加相对路径的文件:
path = "/".join(script_directory) + "/" + rel_path
现在您可以对文件执行任何操作,例如:
file = open(path)
【讨论】:
你应该使用path = os.path.join(script_directory, rel_path)
中的os模块而不是path = "/".join(script_directory) + "/" + rel_path
。而不是手动解析路径你应该使用script_path = os.path.dirname(__file__)
【参考方案11】:
import os
def file_path(relative_path):
dir = os.path.dirname(os.path.abspath(__file__))
split_path = relative_path.split("/")
new_path = os.path.join(dir, *split_path)
return new_path
with open(file_path("2091/data.txt"), "w") as f:
f.write("Powerful you have become.")
【讨论】:
【参考方案12】:当我还是初学者时,我发现这些描述有点吓人。一开始我会尝试
For Windows
f= open('C:\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f)
这会引发syntax error
。我曾经很困惑。然后在谷歌上浏览了一番之后。找到了错误发生的原因。 为初学者写这篇文章
这是因为要在 Unicode 中读取路径,您只需在启动文件路径时添加 \
f= open('C:\\Users\chidu\Desktop\Skipper New\Special_Note.txt','w+')
print(f)
现在只需在启动目录之前添加\
即可。
【讨论】:
反斜杠是多个字符的转义字符。如果您碰巧遇到\t
,例如\top\directory
,则'\t' 会被解释为制表符,并且您的'trick' 会失败。最好的选择是使用原始字符串格式r'C:\Users\chidu\Desktop\Skipper New\Special_Note.txt'
,它不会尝试“转义”字符。【参考方案13】:
获取父文件夹的路径,然后os.join
你的相关文件到最后。
# get parent folder with `os.path`
import os.path
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
file = "config.yaml"
final_path = os.path.join(BASE_DIR, file)
# get parent folder with `pathlib`'s Path
from pathlib import Path
BASE_DIR = Path(__file__).absolute().parent
file = "config.yaml"
final_path = BASE_DIR / file
【讨论】:
所有大写的名字都应该保留给常量 在这种情况下,BASE_DIR 不是常量吗?正在运行的脚本的父文件夹在运行时不会改变。【参考方案14】:Since Python 3.4你可以以面向对象的方式访问对象:
folder = Path(os.getcwd())
path = folder / "2091" / "sample.txt"
with path.open('r+') as fp:
# do magic
with
关键字还将确保您的资源正确关闭,即使您遇到了一些讨厌的Exception
【讨论】:
以上是关于在 Python 中的相对位置打开文件的主要内容,如果未能解决你的问题,请参考以下文章