如何可靠地打开与 Python 脚本相同目录中的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4060221/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reliably open a file in the same directory as a Python script
提问by dln385
I used to open files that were in the same directory as the currently running Python script by simply using a command like
我曾经通过简单地使用类似的命令来打开与当前运行的 Python 脚本位于同一目录中的文件
open("Some file.txt", "r")
However, I discovered that when the script was run in Windows by double-clicking it, it would try to open the file from the wrong directory.
但是,我发现当脚本在 Windows 中通过双击运行时,它会尝试从错误的目录打开文件。
Since then I've used a command of the form
从那时起,我使用了以下形式的命令
open(os.path.join(sys.path[0], "Some file.txt"), "r")
whenever I wanted to open a file. This works for my particular usage, but I'm not sure if sys.path[0]might fail in some other use case.
每当我想打开文件时。这适用于我的特定用法,但我不确定sys.path[0]在其他一些用例中是否会失败。
So my question is: What is the best and most reliable way to open a file that's in the same directory as the currently running Python script?
所以我的问题是:打开与当前运行的 Python 脚本位于同一目录中的文件的最佳和最可靠的方法是什么?
Here's what I've been able to figure out so far:
到目前为止,这是我能够弄清楚的:
os.getcwd()andos.path.abspath('')return the "current working directory", not the script directory.os.path.dirname(sys.argv[0])andos.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]andos.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.
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]))似乎返回脚本目录。我不确定这两者之间是否有任何区别。
Edit:
编辑:
I just realized that what I want to do would be better described as "open a file in the same directory as the containing module". In other words, if I import a module I wrote that's in another directory, and that module opens a file, I want it to look for the file in the module's directory. I don't think anything I've found is able to do that...
我刚刚意识到我想要做的最好描述为“在包含模块的同一目录中打开一个文件”。换句话说,如果我导入我在另一个目录中编写的模块,并且该模块打开一个文件,我希望它在模块目录中查找该文件。我认为我发现的任何东西都无法做到这一点......
回答by André Caron
I always use:
我总是使用:
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
The join()call prepends the current working directory, but the documentation says that if some path is absolute, all other paths left of it are dropped. Therefore, getcwd()is dropped when dirname(__file__)returns an absolute path.
该join()调用将当前工作目录放在前面,但文档说如果某个路径是绝对路径,则其左侧的所有其他路径都将被删除。因此,getcwd()当dirname(__file__)返回绝对路径时被丢弃。
Also, the realpathcall resolves symbolic links if any are found. This avoids troubles when deploying with setuptools on Linux systems (scripts are symlinked to /usr/bin/-- at least on Debian).
此外,realpath如果找到任何符号链接,调用将解析符号链接。这避免了在 Linux 系统上使用 setuptools 进行部署时的麻烦(脚本被符号链接到/usr/bin/——至少在 Debian 上)。
You may the use the following to open up files in the same folder:
您可以使用以下命令打开同一文件夹中的文件:
f = open(os.path.join(__location__, 'bundled-resource.jpg'));
# ...
I use this to bundle resources with several Django application on both Windows and Linux and it works like a charm!
我用它来将资源与 Windows 和 Linux 上的几个 Django 应用程序捆绑在一起,它的作用就像一个魅力!
回答by dcolish
I'd do it this way:
我会这样做:
from os.path import abspath, exists
f_path = abspath("fooabar.txt")
if exists(f_path):
with open(f_path) as f:
print f.read()
The above code builds an absolute path to the file using abspathand is equivalent to using normpath(join(os.getcwd(), path))[that's from the pydocs]. It then checks if that file actually existsand then uses a context manager to open it so you don't have to remember to call close on the file handle. IMHO, doing it this way will save you a lot of pain in the long run.
上面的代码使用abspath构建文件的绝对路径,相当于使用normpath(join(os.getcwd(), path))[that's from the pydocs]。然后它检查该文件是否确实存在,然后使用上下文管理器打开它,这样您就不必记住在文件句柄上调用 close。恕我直言,从长远来看,这样做会为您节省很多痛苦。
回答by Zimm3r
Ok here is what I do
好的,这就是我所做的
sys.argv is always what you type into the terminal or use as the file path when executing it with python.exe or pythonw.exe
sys.argv 始终是您在终端中键入的内容或在使用 python.exe 或 pythonw.exe 执行时用作文件路径的内容
For example you can run the file text.py several ways, they each give you a different answer they always give you the path that python was typed.
例如,您可以通过多种方式运行文件 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
Ok so know you can get the file name, great big deal, now to get the application directory you can know use os.path, specifically abspath and dirname
好的,所以知道你可以得到文件名,很重要,现在要得到你可以使用 os.path 知道的应用程序目录,特别是 abspath 和 dirname
import sys, os
print os.path.dirname(os.path.abspath(sys.argv[0]))
That will output this:
这将输出:
C:\Documents and Settings\Admin\
it will always output this no matter if you type python test.py or python "C:\Documents and Settings\Admin\test.py"
无论你输入 python test.py 还是 python "C:\Documents and Settings\Admin\test.py",它都会输出这个
The problem with using __file__Consider these two files 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
导入_test.py
import test
import sys
test.paths()
print "--------"
print __file__
print sys.argv[0]
Output of "python test.py"
“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
Output of "python test_import.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
So as you can see filegives you always the python file it is being run from, where as sys.argv[0] gives you the file that you ran from the interpreter always. Depending on your needs you will need to choose which one best fits your needs.
因此,如您所见,file始终为您提供运行它的 python 文件,而 sys.argv[0] 始终为您提供从解释器运行的文件。根据您的需要,您需要选择最适合您需要的一种。
回答by RED MONKEY
To quote from the Python documentation:
引用 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.
在程序启动时初始化,此列表的第一项 path[0] 是包含用于调用 Python 解释器的脚本的目录。如果脚本目录不可用(例如,如果以交互方式调用解释器或从标准输入读取脚本),则 path[0] 是空字符串,它指示 Python 首先搜索当前目录中的模块。请注意,脚本目录插入在作为 PYTHONPATH 的结果插入的条目之前。
sys.path[0] is what you are looking for.
sys.path[0] 就是你要找的。

