首页 文章

如何在与Python脚本相同的目录中可靠地打开文件

提问于
浏览
116

我曾经只使用像这样的命令打开与当前运行的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('') 返回"current working directory",而不是脚本目录 .

  • os.path.dirname(sys.argv[0])os.path.dirname(__file__) 返回用于调用脚本的路径,该路径可能是相对的,甚至是空白的(如果脚本在cwd中) . 此外,当脚本在IDLE或PythonWin中运行时, __file__ 不存在 .

  • sys.path[0]os.path.abspath(os.path.dirname(sys.argv[0])) 似乎返回脚本目录 . 我'm not sure if there'这两者之间有什么区别 .

Edit:

我刚刚意识到我想做的事情会更好地描述为“在与包含模块相同的目录中打开一个文件” . 换句话说,如果我导入了一个模块,我在另一个目录中编写了该模块,并且该模块打开了一个文件,我希望它在模块的目录中查找该文件 . 我认为我发现的任何东西都不能做到这一点......

4 回答

  • 1

    我一直用:

    __location__ = os.path.realpath(
        os.path.join(os.getcwd(), os.path.dirname(__file__)))
    

    join() 调用前置当前工作目录,但是文档说如果某个路径是绝对路径,那么它的所有其他路径都将被删除 . 因此,当 dirname(__file__) 返回绝对路径时, getcwd() 将被删除 .

    此外, realpath 调用解析符号链接(如果找到) . 这避免了在Linux系统上使用setuptools进行部署时的麻烦(脚本符号链接到 /usr/bin/ - 至少在Debian上) .

    您可以使用以下命令打开同一文件夹中的文件:

    f = open(os.path.join(__location__, 'bundled-resource.jpg'));
    # ...
    

    我使用它在Windows和Linux上捆绑资源和几个Django应用程序,它就像一个魅力!

  • 137

    引用Python文档:

    在程序启动时初始化时,此列表的第一项path [0]是包含用于调用Python解释器的脚本的目录 . 如果脚本目录不可用(例如,如果以交互方式调用解释器或者从标准输入读取脚本),则路径[0]为空字符串,它指示Python首先搜索当前目录中的模块 . 请注意,在作为PYTHONPATH的结果插入条目之前插入了脚本目录 .

    sys.path [0]正是您要找的 .

  • 27

    好的,这就是我的工作

    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”,它将始终输出此值

    The problem with using 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]为您提供始终从解释器运行的文件 . 根据您的需求,您需要选择最适合您需求的产品 .

  • 16

    我这样做:

    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] . 然后它检查该文件是否实际exists然后使用上下文管理器打开它,这样您就不必记得在文件句柄上调用close . 恕我直言,这样做会从长远来看为你节省很多痛苦 .

相关问题