【问题标题】:Get caller function's absolute path to its file?获取调用者函数到其文件的绝对路径?
【发布时间】:2019-04-02 07:46:35
【问题描述】:

如果文件a.py中有方法t1并且有一个文件b.py,它从a.py文件中调用方法t1。如何在t1 方法中获取b.py 文件的完整/绝对路径?

使用检查模块(就像这里:how to get the caller's filename, method name in python),我可以获得文件的相对路径,但它似乎不包含绝对路径(或者有一些其他属性对象,可以访问它?)。

举个例子:

a.py:

def t1():
    print('callers absolute path')

b.py:

from a import t1
t1()  # should print absolute path for `b.py`

【问题讨论】:

  • 不应该t1()返回a.py的绝对路径吗?
  • 所以你问如何将相对路径变成绝对路径...?
  • @DirtyBit 没有。要获取a.py 路径,您只需使用__file__sys.path[0]。但我需要调用者的路径,而不是被调用方法的路径。
  • @Aran-Fey 如果它不返回绝对路径,那么是的。我想知道与os.path.realpath 结合使用是否会一直返回正确的绝对路径?原因realpath 函数将当前工作目录与相对路径结合起来。
  • __file__ 始终是有效路径,即是的,它与当前工作目录相关。 (除非您在代码中更改了 CWD,但这是您自己的错……)

标签: python python-3.x path


【解决方案1】:
import os
import inspect


def get_cfp(real: bool = False) -> str:
    """Return caller's current file path.

    Args:
        real: if True, returns full path, otherwise relative path
            (default: {False})
    """
    frame = inspect.stack()[1]
    p = frame[0].f_code.co_filename
    if real:
        return os.path.realpath(p)
    return p

从另一个模块运行:

from module import my_module
p1 = my_module.get_cfp()
p2 = my_module.get_cfp(real=True)
print(p1)
print(p2)

打印:

test_path/my_module_2.py
/home/user/python-programs/test_path/my_module_2.py

【讨论】:

  • frame = inspect.stack()[1] p = frame[0].f_code.co_filename - 非常有用的行。经过一些编辑后,我将其包含在我的本地专有包中,以便将一些文件保存在调用脚本所在的同一文件夹中(而不是一直使用 os 更改相对路径或传递整个路径字符串)。谢谢!
【解决方案2】:

使用sys._getframe()

a1.py

import sys
def t1():
    print(sys._getframe().f_code)

a2.py

from a1 import t1
t1()  # should print absolute path for `b.py`

因此

py -m a2.py

输出

<code object t1 at 0x0000029BF394AB70, file "C:\Users\dirtybit\PycharmProjects\a1.py", line 2>

编辑

使用inspect

a1.py

import inspect
def t1():
    print("Caller: {}".format(inspect.getfile(inspect.currentframe())))

a2.py

from a1 import t1
t1()  # should print absolute path for `b.py`

输出

Caller: C:\Users\dirtybit\PycharmProjects\a1.py

【讨论】:

    【解决方案3】:

    您可以通过 python 中的os 模块获取它。

    >>> import a
    >>> os.path.abspath(a.__file__)
    

    【讨论】:

    • 这将为您提供当前文件的路径,而不是调用者文件的路径。
    【解决方案4】:

    使用 os 模块,您可以执行以下操作:

    a.py

    import os
    
    def t1(__file__):
        print(os.path.abspath(__file__))
    

    b.py

    from a import t1
    t1(__file__)  # shoult print absolute path for `b.py`
    

    这样,您可以调用t1(__file__ 并获取任何文件的绝对路径。

    【讨论】:

    • 我知道,但这不是我需要的。我需要在a.py 中找到该路径。 a.py 的工作应该是提供这些,而不是 b.py
    • 打印(os.path.abspath("b.py"))
    • 好吧,你仍然需要提供调用者文件名,所以不好:)
    【解决方案5】:

    诀窍在于恢复当前工作目录该目录到调用者文件的相对路径(此处为b.py)。连接完成其余的工作。

    a.py:

        import os
        import sys
        def t1():
            namespace = sys._getframe(1).f_globals
            cwd = os.getcwd()
            rel_path = namespace['__file__']
            abs_path= os.path.join(cwd,rel_path)
            print('callers absolute path!',abs_path)
    

    b.py:

        from a import t1
        t1()  # prints absolute path for `b.py`
    

    不幸的是,这个技巧不适用于 jupyter notebooks..

    【讨论】:

      猜你喜欢
      • 2020-03-19
      • 1970-01-01
      • 1970-01-01
      • 2012-04-24
      • 2010-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多