我过去常常打开与当前运行的Python脚本在同一目录下的文件,只需使用如下命令:

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

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

从那以后,我一直使用表单的命令

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

每当我想打开一个文件。这适用于我的特定用法,但我不确定sys。路径[0]可能在其他用例中失败。

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

以下是我目前所了解到的情况:

os.getcwd() and os.path.abspath('') return the "current working directory", not the script directory. os.path.dirname(sys.argv[0]) and os.path.dirname(__file__) return the path used to call the script, which may be relative or even blank (if the script is in the cwd). Also, __file__ does not exist when the script is run in IDLE or PythonWin. sys.path[0] and os.path.abspath(os.path.dirname(sys.argv[0])) seem to return the script directory. I'm not sure if there's any difference between these two.

编辑:

我刚刚意识到,我想做的事情应该更好地描述为“在包含模块的同一目录中打开一个文件”。换句话说,如果我导入了一个我在另一个目录下编写的模块,而该模块打开了一个文件,我希望它在模块的目录下查找该文件。我不认为我发现的任何东西都能做到这一点……


当前回答

我会这样做:

from os.path import abspath, exists

f_path = abspath("fooabar.txt")

if exists(f_path):
    with open(f_path) as f:
        print f.read()

上面的代码使用abspath构建文件的绝对路径,等价于使用normpath(join(os.getcwd(), path))[来自pydocs]。然后它检查该文件是否实际存在,然后使用上下文管理器打开它,这样您就不必记得在文件句柄上调用close。恕我直言,从长远来看,这样做会为你省去很多痛苦。

其他回答

我总是用:

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

join()调用将当前工作目录放在前面,但是文档说,如果某个路径是绝对路径,则丢弃它剩下的所有其他路径。因此,当dirname(__file__)返回一个绝对路径时,getcwd()将被删除。

此外,如果找到符号链接,realpath调用将解析符号链接。这避免了在Linux系统上使用setuptools部署时的麻烦(脚本被符号链接到/usr/bin/—至少在Debian上)。

您可以使用以下方法打开同一文件夹中的文件:

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

我用它在Windows和Linux上与几个Django应用程序绑定资源,它的工作就像一个魅力!

引用Python文档:

As initialized upon program startup, the first item of this list, path[0], is the directory containing the script that was used to invoke the Python interpreter. If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input), path[0] is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result of PYTHONPATH.

如果从终端运行脚本,则sys. exe。路径[0]就是你要找的。

然而,如果你有:

barpath/bar.py
    import foopath.foo

foopath/foo.py
    print sys.path[0]  # you get barpath

所以要小心!

因为我在尝试使用__file__或sys。我是这样做的:

from inspect import getfile
from pathlib import Path


script_path = getfile(lambda: None)
print(script_path)
parent_path = Path(script_path).parent
print(parent_path)

with open(parent_path/'Some file.txt', 'r') as obFile:
    print(obFile.read())

你能试试这个简单的方法吗?

    import os

    my_local_file = os.path.join(os.path.dirname(__file__), 'some_file.txt')

    f = open(my_local_file,  "r")
    my_local_data = f.read()

我会这样做:

from os.path import abspath, exists

f_path = abspath("fooabar.txt")

if exists(f_path):
    with open(f_path) as f:
        print f.read()

上面的代码使用abspath构建文件的绝对路径,等价于使用normpath(join(os.getcwd(), path))[来自pydocs]。然后它检查该文件是否实际存在,然后使用上下文管理器打开它,这样您就不必记得在文件句柄上调用close。恕我直言,从长远来看,这样做会为你省去很多痛苦。