如何可靠地在当前运行脚本的目录中打开文件

14 浏览
0 Comments

如何可靠地在当前运行脚本的目录中打开文件

在以前,我通常通过以下命令打开与当前运行的Python脚本位于同一目录的文件:

open("Some file.txt", "r")

然而,我发现当在Windows上双击运行脚本时,它会尝试从错误的目录打开文件。

从那时起,每当我想要打开一个文件时,我都会使用以下形式的命令:

open(os.path.join(sys.path[0], "Some file.txt"), "r")

这可以满足我特定的使用需求,但我不确定sys.path[0]在其他情况下是否会失败。

所以我的问题是:打开与当前运行的Python脚本位于同一目录的文件的最佳且最可靠的方法是什么?

以下是我目前能够找出的信息:

  • os.getcwd()os.path.abspath('')返回的是"当前工作目录",而不是脚本目录。

  • os.path.dirname(sys.argv[0])os.path.dirname(__file__)返回用于调用脚本的路径,这可能是相对路径甚至是空白(如果脚本在当前工作目录中)。此外,当在IDLE或PythonWin中运行脚本时,__file__不存在。

  • sys.path[0]os.path.abspath(os.path.dirname(sys.argv[0]))似乎返回脚本目录。我不确定这两者之间是否有任何区别。

编辑:

我刚刚意识到,更准确地说,我想做的是"在包含模块的同一目录中打开文件"。换句话说,如果我导入了一个位于另一个目录中的模块,并且该模块打开了一个文件,我希望它在模块的目录中查找该文件。我不认为我找到的任何方法能够实现这一点...

0
0 Comments

如何可靠地在当前运行脚本的目录中打开文件

问题的出现原因:

根据Python文档的描述,当程序启动时,sys.path[0]是包含调用Python解释器的脚本的目录。但是,如果脚本目录不可用(例如,如果通过交互方式调用解释器或者从标准输入读取脚本),sys.path[0]将为空字符串,这会导致Python首先在当前目录中搜索模块。这就是问题的出现原因。

解决方法:

- 如果你是在终端上运行脚本,sys.path[0]就是你要找的路径。

- 要获取文件的完整路径,可以使用os.path.join(sys.path[0], 'some file.txt')。这样可以在所有系统上正确处理空格和斜杠。

- 不要依赖sys.argv来告诉你脚本的名称!在确定脚本目录时,使用__file__

要可靠地在当前运行脚本的目录中打开文件,可以使用sys.path[0]__file__来获取脚本所在的目录,并使用os.path.join()来拼接文件的完整路径。这样可以确保在不同的环境中都能正确地打开文件。

0
0 Comments

Python 3.4版本引入了pathlib模块,并且下面的代码可以可靠地在当前脚本的同一目录中打开一个文件:

from pathlib import Path
p = Path(__file__).with_name('file.txt')
with p.open('r') as f:
    print(f.read())

如果你需要将文件路径作为字符串传递给某些类似于open的API,可以使用absolute()方法来获取它:

p = Path(__file__).with_name('file.txt')
filename = p.absolute()

需要注意的是,Python的REPL(交互式解释器)如使用python命令或ipython运行时不会暴露__file__属性。

0
0 Comments

如何可靠地在当前运行脚本的目录中打开文件

在编写Python脚本时,经常需要在与当前脚本相同的目录中打开文件。然而,处理文件路径时可能会遇到一些问题。本文将介绍出现这些问题的原因以及解决方法。

在处理文件路径时,我们通常使用以下代码来获取当前脚本所在的目录:

__location__ = os.path.realpath(
    os.path.join(os.getcwd(), os.path.dirname(__file__)))

其中,`__file__`代表当前脚本的文件路径。此代码使用了`os.path.join()`函数将当前工作目录与`os.path.dirname(__file__)`拼接在一起,然后使用`os.path.realpath()`函数获取其绝对路径。

然而,需要注意的是,如果路径是绝对路径,那么所有在该路径左侧的路径都会被忽略。因此,当`dirname(__file__)`返回的是绝对路径时,`getcwd()`函数返回的当前工作目录会被忽略。

另外,`realpath()`函数还可以解析符号链接。这在在Linux系统上使用setuptools部署时非常有用(脚本被符号链接到`/usr/bin/`目录下)。

要在当前目录中打开文件,可以使用以下代码:

f = open(os.path.join(__location__, 'bundled-resource.jpg'))
# ...

以上代码将文件路径拼接到`__location__`变量中,然后使用`open()`函数打开文件。

此方法在在Windows和Linux上使用Django应用程序时非常有效。

如果不能使用`__file__`,则可以使用`sys.argv[0]`来代替`dirname(__file__)`。其他部分的代码应该如预期地工作。我喜欢使用`__file__`,因为在库代码中,`sys.argv[0]`可能根本不指向你的代码,特别是当通过某个第三方脚本导入时。

然而,使用`__file__`存在一个问题,那就是当脚本直接从解释器运行时和当脚本被导入时,结果会有所不同。要了解`file`和`sys.argv[0]`之间的区别,请参考我的答案。

因此,使用`realpath( join( getcwd(), dirname(__file__) ))`可以解决Zimm3r答案中描述的这种变化的问题。

不需要使用`getcwd()`,因为`os.path.abspath()`函数已经为我们做了这个工作。而`os.path.realpath()`函数会调用`os.path.abspath()`函数。

更现代的做法是使用`pathlib.Path(__file__).parent / 'Some file.txt'`来打开文件。

如果要打开位于当前目录的子文件夹中的文件(例如"Images/bundled-resource.jpg"),可以将文件路径适配为:

f = open(os.path.join(__location__, 'Images', 'bundled-resource.jpg'))
# ...

以上就是解决在当前运行脚本的目录中可靠地打开文件的方法。

0