How to reliably open a file in the same directory as a Python script
我以前只需使用如下命令就可以打开与当前运行的python脚本位于同一目录中的文件
1 | open("Some file.txt","r") |
但是,我发现当在Windows中双击脚本时,它会试图从错误的目录打开文件。
从那以后我就用了一个命令
1 | open(os.path.join(sys.path[0],"Some file.txt"),"r") |
号
只要我想打开一个文件。这适用于我的特定用法,但我不确定
所以我的问题是:打开与当前运行的python脚本位于同一目录下的文件的最佳和最可靠的方法是什么?
以下是迄今为止我所能理解的:
os.getcwd() 和os.path.abspath('') 返回"当前工作目录",而不是脚本目录。os.path.dirname(sys.argv[0]) 和os.path.dirname(__file__) 返回用于调用脚本的路径,路径可以是相对路径,也可以是空白路径(如果脚本在cwd中)。另外,当脚本在空闲或pythonwin中运行时,__file__ 不存在。sys.path[0] 和os.path.abspath(os.path.dirname(sys.argv[0])) 似乎返回了脚本目录。我不确定这两者是否有什么区别。
编辑:
我刚刚意识到我想要做的是更好地描述为"在与包含模块相同的目录中打开一个文件"。换句话说,如果我导入一个写在另一个目录中的模块,并且该模块打开一个文件,我希望它在模块的目录中查找该文件。我认为我所发现的一切都无法做到…
我总是使用:
1 2 | __location__ = os.path.realpath( os.path.join(os.getcwd(), os.path.dirname(__file__))) |
另外,如果找到符号链接,
可以使用以下方法打开同一文件夹中的文件:
1 2 | 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.path[0]是您要查找的。
好的,这是我的工作
使用python.exe或pythonw.exe执行时,sys.argv始终是您在终端中键入或用作文件路径的内容。
例如,您可以通过多种方式运行文件text.py,每种方式都为您提供不同的答案,它们总是为您提供键入python的路径。
1 2 3 4 | C:\Documents and Settings\Admin>python test.py sys.argv[0]: test.py C:\Documents and Settings\Admin>python"C:\Documents and Settings\Admin\test.py" sys.argv[0]: C:\Documents and Settings\Admin\test.py |
。
好的,那么知道你可以得到文件名,非常重要,现在要得到应用程序目录,你可以知道使用os.path,特别是abspath和dirname。
1 2 | import sys, os print os.path.dirname(os.path.abspath(sys.argv[0])) |
这将输出:
1 | C:\Documents and Settings\Admin\ |
。
无论您键入python test.py还是python"c:documents and settingsadmin est.py",它都将始终输出此信息。
使用文件的问题__考虑这两个文件测试.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import sys import os def paths(): print"__file__: %s" % __file__ print"sys.argv: %s" % sys.argv[0] a_f = os.path.abspath(__file__) a_s = os.path.abspath(sys.argv[0]) print"abs __file__: %s" % a_f print"abs sys.argv: %s" % a_s if __name__ =="__main__": paths() |
。
导入测试.py
1 2 3 4 5 6 7 8 | import test import sys test.paths() print"--------" print __file__ print sys.argv[0] |
输出"python test.py"
1 2 3 4 5 | C:\Documents and Settings\Admin>python test.py __file__: test.py sys.argv: test.py abs __file__: C:\Documents and Settings\Admin\test.py abs sys.argv: C:\Documents and Settings\Admin\test.py |
。
输出"python test_import.py"
1 2 3 4 5 6 7 8 | C:\Documents and Settings\Admin>python test_import.py __file__: C:\Documents and Settings\Admin\test.pyc sys.argv: test_import.py abs __file__: C:\Documents and Settings\Admin\test.pyc abs sys.argv: C:\Documents and Settings\Admin\test_import.py -------- test_import.py test_import.py |
因此,正如您所看到的,文件总是为您提供运行它的python文件,而sys.argv[0]总是为您提供从解释器运行的文件。根据你的需要,你需要选择最适合你需要的。
我会这样做:
1 2 3 4 5 6 7 | 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构建文件的绝对路径,相当于使用