我曾经只是使用像这样的命令打开与当前运行的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__)
返回用于调用脚本的路径,该路径可能是相对的,甚至是空白的(如果脚本在cwd中).此外,__file__
当脚本在IDLE或PythonWin中运行时不存在.
sys.path[0]
并且os.path.abspath(os.path.dirname(sys.argv[0]))
似乎返回脚本目录.我不确定这两者之间是否有任何区别.
编辑:
我刚刚意识到我想做的事情会更好地描述为"在与包含模块相同的目录中打开一个文件".换句话说,如果我导入了一个我在另一个目录中编写的模块,并且该模块打开了一个文件,我希望它在模块的目录中查找该文件.我认为我发现的任何东西都不能做到这一点......
我一直用:
__location__ = os.path.realpath( os.path.join(os.getcwd(), os.path.dirname(__file__)))
该join()
调用会在当前工作目录之前进行,但文档说如果某个路径是绝对路径,则会删除其余的所有路径.因此,getcwd()
在dirname(__file__)
返回绝对路径时被删除.
此外,realpath
如果找到任何符号链接,则调用将解析符号链接.这避免了在Linux系统上使用setuptools进行部署时的麻烦(脚本符号链接到/usr/bin/
- 至少在Debian上).
您可以使用以下命令打开同一文件夹中的文件:
f = open(os.path.join(__location__, 'bundled-resource.jpg')); # ...
我使用它在Windows和Linux上捆绑资源和几个Django应用程序,它就像一个魅力!
引用Python文档:
在程序启动时初始化时,此列表的第一项path [0]是包含用于调用Python解释器的脚本的目录.如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),path [0]是空字符串,它指示Python首先搜索当前目录中的模块.请注意,在作为PYTHONPATH结果插入的条目之前插入了脚本目录.
sys.path [0]正是您要找的.
好的,这就是我的工作
sys.argv始终是您在终端中键入的内容,或者在使用python.exe或pythonw.exe执行时用作文件路径
例如,您可以通过多种方式运行text.py文件,它们每个都会给您一个不同的答案,它们总是为您提供键入python的路径.
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
import sys, os print os.path.dirname(os.path.abspath(sys.argv[0]))
这将输出:
C:\Documents and Settings\Admin\
如果输入python test.py或python"C:\ Documents and Settings\Admin\test.py",它将始终输出此值
使用__file__的问题 考虑这两个文件test.py
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()
import_test.py
import test import sys test.paths() print "--------" print __file__ print sys.argv[0]
输出"python test.py"
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"
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
因此,您可以看到file始终为您提供运行的python文件,其中sys.argv [0]为您提供始终从解释器运行的文件.根据您的需求,您需要选择最适合您需求的产品.