首页 文章

如何在Python中获取当前执行文件的路径?

提问于
浏览
168

这似乎是一个新手问题,但事实并非如此 . 一些常见的方法并不适用于所有情况:

sys.argv [0]

这意味着使用 path = os.path.abspath(os.path.dirname(sys.argv[0])) ,但如果您从另一个目录中的另一个Python脚本运行,则这不起作用,这可能发生在现实生活中 .

file

这意味着使用 path = os.path.abspath(os.path.dirname(__file__)) ,但我发现这不起作用:

  • py2exe 没有 __file__ 属性,但有一个workaround

  • 当您使用 execute() 从IDLE运行时,没有 __file__ 属性

  • OS X 10.6我得到 NameError: global name '__file__' is not defined

回答不完整的相关问题:

我正在寻找一个适用于所有上述用例的 generic solution .

更新

这是测试用例的结果:

python a.py的输出(在Windows上)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

a.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

subdir / b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

C:.
|   a.py
\---subdir
        b.py

11 回答

  • 6

    您无法直接确定正在执行的主脚本的位置 . 毕竟,有时脚本根本不是来自文件 . 例如,它可以来自交互式解释器或仅存储在存储器中的动态生成的代码 .

    但是,您可以可靠地确定模块的位置,因为模块始终从文件加载 . 如果使用以下代码创建模块并将其放在与主脚本相同的目录中,则主脚本可以导入模块并使用它来定位自身 .

    SOME_PATH / module_locator.py:

    def we_are_frozen():
        # All of the modules are built-in to the interpreter, e.g., by py2exe
        return hasattr(sys, "frozen")
    
    def module_path():
        encoding = sys.getfilesystemencoding()
        if we_are_frozen():
            return os.path.dirname(unicode(sys.executable, encoding))
        return os.path.dirname(unicode(__file__, encoding))
    

    SOME_PATH / main.py:

    import module_locator
    my_path = module_locator.module_path()
    

    如果在不同目录中有多个主脚本,则可能需要多个module_locator副本 .

    当然,如果您的主脚本是由某些其他工具加载的,这些工具不允许您导入与您的脚本位于同一位置的模块,那么您就不走运了 . 在这种情况下,您所追求的信息根本不存在于您的程序中的任何位置 . 您最好的选择是向该工具的作者提交错误 .

  • 0

    首先,您需要从 inspectos 导入

    from inspect import getsourcefile
    from os.path import abspath
    

    接下来,无论您想从哪里找到源文件,只需使用即可

    abspath(getsourcefile(lambda:0))
    
  • 77

    我遇到了类似的问题,我认为这可能会解决问题:

    def module_path(local_function):
       ''' returns the module path without the use of __file__.  Requires a function defined
       locally in the module.
       from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
       return os.path.abspath(inspect.getsourcefile(local_function))
    

    它适用于常规脚本和空闲 . 我只能说是为别人试试吧!

    我的典型用法:

    from toolbox import module_path
    def main():
       pass # Do stuff
    
    global __modpath__
    __modpath__ = module_path(main)
    

    现在我使用__modpath__而不是__file__ .

  • 2

    简短的回答是 there is no guaranteed way to get the information you want ,但是有一些启发式方法几乎总是在实践中起作用 . 你可能会看How do I find the location of the executable in C? . 它从C的角度讨论了这个问题,但是提出的解决方案很容易转换成Python .

  • 5

    这个解决方案即使在可执行文件中也很强

    import inspect, os.path
    
    filename = inspect.getframeinfo(inspect.currentframe()).filename
    path     = os.path.dirname(os.path.abspath(filename))
    
  • 3

    有关相关信息,请参阅我对问题Importing modules from parent folder的回答,包括为什么我的答案不使用不可靠的 __file__ 变量 . 这个简单的解决方案应该与不同的操作系统交叉兼容,因为模块 osinspect 是Python的一部分 .

    首先,您需要导入 inspectos 模块的部分内容 .

    from inspect import getsourcefile
    from os.path import abspath
    

    接下来,在Python代码中的任何其他位置使用以下行:

    abspath(getsourcefile(lambda:0))
    

    工作原理:

    从内置模块 os (下面的说明)中,导入 abspath 工具 .

    Mac,NT或Posix的OS例程,具体取决于我们所使用的系统 .

    然后从内置模块 inspect 导入 getsourcefile (以下描述) .

    从实时Python对象中获取有用信息 .

    • abspath(path) 返回文件路径的绝对/完整版本

    • getsourcefile(lambda:0) 以某种方式获取lambda函数对象的内部源文件,因此在Python shell中返回 '<pyshell#nn>' 或返回当前正在执行的Python代码的文件路径 .

    getsourcefile(lambda:0) 的结果上使用 abspath 应确保生成的文件路径是Python文件的完整文件路径 .
    这个解释的解决方案最初是基于How do I get the path of the current executed file in Python?答案的代码 .

  • 2

    这应该以跨平台的方式完成(只要你没有使用解释器或其他东西):

    import os, sys
    non_symbolic=os.path.realpath(sys.argv[0])
    program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
    

    sys.path[0] 是您的调用脚本所在的目录(它首先查找该脚本要使用的模块) . 我们可以在 sys.argv[0] 结尾处取文件本身的名称(这是我用 os.path.basename 做的) . os.path.join 只是坚持他们以跨平台的方式在一起 . os.path.realpath 只是确保我们得到的任何符号链接的名称不同于脚本本身,我们仍然可以得到脚本的真实名称 .

    我没有在一个上测试过这个 . 请告诉我它是否有效,看起来应该如此 . 我使用Python 3.4在Linux(Xubuntu)中测试了这个 . 请注意,针对此问题的许多解决方案都没有听说过Mac上没有 __file__ .

    请注意,如果您的脚本是符号链接,它将为您提供链接到的文件的路径(而不是符号链接的路径) .

  • 13

    您可以使用 pathlib 模块中的 Path

    from pathlib import Path
    
    # ...
    
    Path(__file__)
    

    您可以使用 parent 调用进一步的路径:

    Path(__file__).parent
    
  • 0

    你简单地叫了:

    path = os.path.abspath(os.path.dirname(sys.argv[0]))
    

    代替:

    path = os.path.dirname(os.path.abspath(sys.argv[0]))
    

    abspath() 为您提供 sys.argv[0] 的绝对路径(您的代码所在的文件名), dirname() 返回没有文件名的目录路径 .

  • 47

    只需添加以下内容:

    from sys import *
    path_to_current_file = sys.argv[0]
    print(path_to_current_file)
    

    要么:

    from sys import *
    print(sys.argv[0])
    
  • 1

    如果代码来自文件,您可以获取其全名

    sys._getframe().f_code.co_filename
    

    您还可以将函数名称检索为 f_code.co_name

相关问题