如何可靠地打开与当前运行的脚本位于同一目录中的文件[重复]

2024-12-24 08:56:00
admin
原创
93
摘要:问题描述:我过去常常使用如下命令来打开与当前运行的 Python 脚本位于同一目录中的文件:open("Some file.txt", "r") 但是,我发现当在 Windows 中双击运行该脚本时,它会尝试从错误的目录打开文件。从那时起,我使用以下形式的命令open(...

问题描述:

我过去常常使用如下命令来打开与当前运行的 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 REPLs 例如运行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:

https://stackoverflow.com/questions/10174211/how-to-make-an-always-relative-to-current-module-file-path中推荐了这个答案

解决方案 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。恕我直言,从长远来看,这样做可以为您省去很多麻烦。

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1124  
  IPD(Integrated Product Development,集成产品开发)流程是一种广泛应用于高科技和制造业的产品开发方法论。它通过跨职能团队的紧密协作,将产品开发周期缩短,同时提高产品质量和市场成功率。在IPD流程中,CDCP(Concept Decision Checkpoint,概念决策检查点)是一个关...
IPD培训课程   79  
  研发IPD(集成产品开发)流程作为一种系统化的产品开发方法,已经在许多行业中得到广泛应用。它不仅能够提升产品开发的效率和质量,还能够通过优化流程和资源分配,显著提高客户满意度。客户满意度是企业长期成功的关键因素之一,而IPD流程通过其独特的结构和机制,能够确保产品从概念到市场交付的每个环节都围绕客户需求展开。本文将深入...
IPD流程   70  
  IPD(Integrated Product Development,集成产品开发)流程是一种以跨职能团队协作为核心的产品开发方法,旨在通过优化资源分配、提高沟通效率以及减少返工,从而缩短项目周期并提升产品质量。随着企业对产品上市速度的要求越来越高,IPD流程的应用价值愈发凸显。通过整合产品开发过程中的各个环节,IPD...
IPD项目管理咨询   82  
  跨部门沟通是企业运营中不可或缺的一环,尤其在复杂的产品开发过程中,不同部门之间的协作效率直接影响项目的成败。集成产品开发(IPD)作为一种系统化的项目管理方法,旨在通过优化流程和增强团队协作来提升产品开发的效率和质量。然而,跨部门沟通的复杂性往往成为IPD实施中的一大挑战。部门之间的目标差异、信息不对称以及沟通渠道不畅...
IPD是什么意思   74  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用