如何可靠地打开与当前运行的脚本位于同一目录中的文件[重复]
- 2024-12-24 08:56:00
- admin 原创
- 94
问题描述:
我过去常常使用如下命令来打开与当前运行的 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]))
似乎返回了脚本目录。我不确定这两者之间是否有区别。
编辑:
我刚刚意识到,我想要做的事情最好被描述为“打开与包含模块相同的目录中的文件”。换句话说,如果我导入我编写的位于另一个目录中的模块,并且该模块打开一个文件,我希望它在模块的目录中查找该文件。我认为我发现的任何东西都无法做到这一点……
解决方案 1:
我总是使用:
__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 应用程序捆绑在一起,效果非常好!
解决方案 2:
在 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
s 例如运行python
没有目标的命令或ipython
不暴露__file__
。
解决方案 3:
引用 Python 文档:
在程序启动时初始化时,此列表的第一项 path[0] 是包含用于调用 Python 解释器的脚本的目录。如果脚本目录不可用(例如,如果以交互方式调用解释器,或者如果从标准输入读取脚本),path[0] 为空字符串,这会指示 Python 首先在当前目录中搜索模块。请注意,脚本目录插入在 PYTHONPATH 结果插入的条目之前。
如果您从终端运行脚本,sys.path[0]
那么这就是您正在寻找的。
但是,如果您有:
barpath/bar.py
import foopath.foo
foopath/foo.py
print sys.path[0] # you get barpath
所以要小心!
解决方案 4:
好的,这就是我要做的
sys.argv 始终是您在终端中输入的内容,或在使用 python.exe 或 pythonw.exe 执行时用作文件路径
例如,您可以通过多种方式运行文件 text.py,它们各自给您不同的答案,它们总是给您输入 python 的路径。
C:Documents and SettingsAdmin>python test.py
sys.argv[0]: test.py
C:Documents and SettingsAdmin>python "C:Documents and SettingsAdmin est.py"
sys.argv[0]: C:Documents and SettingsAdmin est.py
好的,现在你可以获取文件名了,这没什么大不了的,现在要获取应用程序目录,你可以使用 os.path,特别是 abspath 和 dirname
import sys, os
print os.path.dirname(os.path.abspath(sys.argv[0]))
这将输出:
C:Documents and SettingsAdmin\n
无论您输入 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()
导入测试.py
import test
import sys
test.paths()
print "--------"
print __file__
print sys.argv[0]
“python test.py”的输出
C:Documents and SettingsAdmin>python test.py
__file__: test.py
sys.argv: test.py
abs __file__: C:Documents and SettingsAdmin est.py
abs sys.argv: C:Documents and SettingsAdmin est.py
“python test_import.py”的输出
C:Documents and SettingsAdmin>python test_import.py
__file__: C:Documents and SettingsAdmin est.pyc
sys.argv: test_import.py
abs __file__: C:Documents and SettingsAdmin est.pyc
abs sys.argv: C:Documents and SettingsAdmin est_import.py
--------
test_import.py
test_import.py
因此,如您所见,file始终为您提供正在运行的 python 文件,而 sys.argv[0] 始终为您提供从解释器运行的文件。根据您的需要,您需要选择最适合您需求的那个。
解决方案 5:
我通常使用下面的方法。它适用于测试,也可能适用于其他用例。
with open(os.path.join(os.path.dirname(__file__), 'some_file.txt'), 'r') as f:
解决方案 6:
您可以尝试一下这样的简单方法吗:
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()
解决方案 7:
因为我尝试使用__file__
或sys.argv[0]
从 emacs 获得错误,所以我这样做:
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())
解决方案 8:
尝试了所有这些解决方案后,我仍然遇到了不同的问题。因此,我发现最简单的方法是创建一个 python 文件:config.py,其中包含一个包含文件绝对路径的字典,并将其导入到脚本中。例如
import config as cfg
import pandas as pd
pd.read_csv(cfg.paths['myfilepath'])
其中 config.py 包含以下内容:
paths = {'myfilepath': 'home/docs/...'}
它不是自动的,但是当您必须在不同的目录或不同的机器上工作时,它是一个很好的解决方案。
解决方案 9:
我会这样做:
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。恕我直言,从长远来看,这样做可以为您省去很多麻烦。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)