【问题标题】:How can I find script's directory? [duplicate]如何找到脚本的目录? [复制]
【发布时间】:2011-06-23 12:25:18
【问题描述】:

考虑以下 Python 代码:

import os
print os.getcwd()

我使用os.getcwd()get the script file's directory location。当我从命令行运行脚本时,它会为我提供正确的路径,而当我从 Django 视图中的代码运行的脚本运行它时,它会打印 /

如何从 Django 视图运行的脚本中获取脚本的路径?

更新:
总结到目前为止的答案 - os.getcwd()os.path.abspath() 都给出了当前工作目录,该目录可能是也可能不是脚本所在的目录。在我的网络主机设置中,__file__ 只给出了没有路径的文件名。

在 Python 中是否有任何方法(总是)能够接收脚本所在的路径?

【问题讨论】:

  • 您应该更仔细地阅读该链接文章。它从不建议使用getcwd 会告诉您脚本的位置。它建议argv[0]dirnameabspath
  • @Rob - 我的虚拟主机上的“print sys.argv[0]”只给出文件名,没有路径
  • @Rob - 这是链接文章“os.getcwd() 返回当前工作目录”的摘录。
  • 是的,但是当前工作目录与您的脚本所在的目录绝对没有关系。与os.chdir 相比,它设置当前工作目录;它不会将您的脚本文件移动到硬盘驱动器上的新位置。 initial 工作目录可能与您的脚本所在的目录相同,但并非总是如此;这篇文章甚至证明了这一点。
  • 请注意,__file__ 将返回脚本上下文的文件名。如果您从 __main__ 调用外部脚本,请注意购买者 - 您可能会得到与预期不同的响应。

标签: python directory django-views getcwd


【解决方案1】:

这对我有用(我通过 this stackoverflow question 找到它)

os.path.realpath(__file__)

【讨论】:

    【解决方案2】:

    您需要在__file__ 上调用os.path.realpath,这样当__file__ 是没有路径的文件名时,您仍然可以获得目录路径:

    import os
    print(os.path.dirname(os.path.realpath(__file__)))
    

    【讨论】:

    • 如果你从解释器内部运行,这将不起作用,因为你会得到NameError: name '__file__' is not defined
    • 我认为这是预期的行为,因为 python 命令不存在于文件中,而是存在于您传递给解释器的字符串中
    • @EhteshChoudhury 那是因为__file__ 是一个模块变量,仅在脚本执行时创建-> 这个变量代表脚本的位置。解释器不是从文件中运行的,所以它不能有这样的变量。
    • 迈克,怎么回事? os.path.dirname(os.path.realpath(__file__)) == sys.path[0] 他们是一样的。
    • 这个解决方案给出了当前文件的目录。如果这是包中的一个模块(即脚本目录的子目录),它与脚本目录相同。如果需要后者,请改用sys.path[0]。要尝试它,请让t/foo.py 打印两个值和仅包含import t.foobar.py
    【解决方案3】:

    试试sys.path[0]

    引用 Python 文档:

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

    来源:https://docs.python.org/library/sys.html#sys.path

    【讨论】:

    • @thang 通常是这样,但这会返回正在运行的脚本的文件路径,而不是被调用脚本的目录。换句话说,如果我从/foo/bar.py 调用脚本/baz.py,此解决方案将返回/foo 而不是所需的/
    • 我遇到了这个解决方案的一个问题。我正在构建一个名为foo 的大型程序,其中主脚本称为__main__.py 并位于foo 目录中。我可以通过运行python foo/__main__.py 或简单地运行python foo 来调用我的程序。对于前者,您的解决方案有效,但对于后者,我最终得到的是相对路径而不是绝对路径。将您的解决方案包装在 os.path.realpath() 中解决了这个问题。
    • 他们 sys.argv[0] 在一种情况下对我来说失败了:当使用 py2app 将我的脚本包装到 MacOS 上的应用程序中时,sys.argv[0] 变成了硬编码的my.app/Contents/Resources/lib/python36.zip,当我所有的支持脚本都在my.app/Contents/Resources 中时。可能是 py2app 的 bug 但证明依赖 argv 还是有点脆弱。
    • 我将脚本作为我的 bin 目录中的符号链接调用到不在我的 PATH 中的可执行 python 文件。但是,sys.path[0] 显示的是我的 bin 目录,而不是正在运行的脚本的绝对路径。
    • sys.path[0] 指的是运行脚本的位置,在大多数情况下,该位置与包含脚本的目录相同。现在,如果您将脚本编译为二进制然后执行它,那么sys.path[0] 将引用 %temp%,因为 exe 从 temp 运行。至少在 Windows 上是这样。
    【解决方案4】:

    我用:

    import os
    import sys
    
    def get_script_path():
        return os.path.dirname(os.path.realpath(sys.argv[0]))
    

    正如 aiham 在评论中指出的那样,您可以在模块中定义此函数并在不同的脚本中使用它。

    【讨论】:

    • +1 因为有用的__file__ 模块属性并不总是被定义。
    • 如果您想将 getScriptPath() 放在不同的模块中但获取实际执行的文件的路径而不是模块路径,这也很有用。
    • @aiham:好点。事实上这个功能在我的框架 utils 模块中:)
    • 请注意,这将返回执行的 Python 脚本的路径。如果您将这些代码打包在其他地方,这些代码将不会返回 Python 文件的源代码。
    • argv[0] 不是查找脚本路径/文件名的可靠方法。它可以是符号链接的名称,也可以是传递给 execve(2) 系统调用的任何其他名称。
    【解决方案5】:

    这是一个相当古老的线程,但是当我从 cron 作业运行 python 脚本时,尝试将文件保存到脚本所在的当前目录时遇到了这个问题。 getcwd() 和许多其他路径都与您的主目录有关。

    获取我使用的脚本的绝对路径

    directory = os.path.abspath(os.path.dirname(__file__))

    【讨论】:

      【解决方案6】:

      试试这个:

      def get_script_path(for_file = None):
          path = os.path.dirname(os.path.realpath(sys.argv[0] or 'something'))
          return path if not for_file else os.path.join(path, for_file)
      

      【讨论】:

        【解决方案7】:

        这就是我最终的结果。如果我在解释器中导入我的脚本,并且如果我将它作为脚本执行,这对我有用:

        import os
        import sys
        
        # Returns the directory the current script (or interpreter) is running in
        def get_script_directory():
            path = os.path.realpath(sys.argv[0])
            if os.path.isdir(path):
                return path
            else:
                return os.path.dirname(path)
        

        【讨论】:

          【解决方案8】:

          这段代码:

          import os
          dn = os.path.dirname(os.path.realpath(__file__))
          

          将“dn”设置为包含当前执行脚本的目录的名称。这段代码:

          fn = os.path.join(dn,"vcb.init")
          fp = open(fn,"r")
          

          将“fn”设置为“script_dir/vcb.init”(以独立于平台的方式)并打开 该文件供当前执行的脚本读取。

          请注意,“当前正在执行的脚本”有些含糊。如果您的整个程序由 1 个脚本组成,那么这就是当前正在执行的脚本,并且“sys.path[0]”解决方案可以正常工作。但是,如果您的应用程序包含脚本 A,它导入一些包“P”,然后调用脚本“B”,那么“P.B”当前正在执行。如果需要获取包含“P.B”的目录,则需要“os.path.realpath(__file__)”解决方案。

          "__file__" 只是给出当前正在执行的(栈顶)脚本的名称:“x.py”。它没有 提供任何路径信息。真正起作用的是“os.path.realpath”调用。

          【讨论】:

            【解决方案9】:
            import os
            script_dir = os.path.dirname(os.path.realpath(__file__)) + os.sep
            

            【讨论】:

              【解决方案10】:
              import os
              exec_filepath = os.path.realpath(__file__)
              exec_dirpath = exec_filepath[0:len(exec_filepath)-len(os.path.basename(__file__))]
              

              【讨论】:

              • 为什么不使用 os.path.dirname?
              • 我不知道 os.path.dirname,也许这也有效。
              【解决方案11】:
              import os,sys
              # Store current working directory
              pwd = os.path.dirname(__file__)
              # Append current directory to the python path
              sys.path.append(pwd)
              

              【讨论】:

              • 这在我的开发机器上运行良好,但在我的网络主机上不起作用 - 我得到 '/'
              • 奇怪,你可以访问 apache conf 文件吗?或者这是一个 Windows 服务器?
              【解决方案12】:

              使用os.path.abspath('')

              【讨论】:

              • 这适用于我的开发机器上的所有内容,但仅适用于我的网络主机上的脚本文件。它不适用于 settings.py,例如以下不起作用:TEMPLATE_DIRS = ((os.path.abspath('')+'/templates'),)
              • 这对我不起作用。我正在通过我的 PATH 中的符号链接调用一个可执行的 python scdript(不在我的 PATH 中)。它只是打印了我的 bin 目录。
              • 哇...这适用于所有困难情况,例如从从父文件夹或 REPL 开始的笔记本运行。这应该是被接受的答案!
              猜你喜欢
              • 2013-10-19
              • 2017-01-15
              • 2019-06-01
              • 2014-11-22
              • 2021-08-05
              • 1970-01-01
              • 1970-01-01
              • 2016-08-05
              • 2013-12-02
              相关资源
              最近更新 更多