获取调用函数所在文件的绝对路径?

5
如果在文件`a.py`中有方法`t1`,并且有一个文件`b.py`,它从`a.py`文件中调用方法`t1`。在方法`t1`中如何获取文件`b.py`的完整/绝对路径?
使用inspect模块(就像这里: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
那么你是在问如何将相对路径转换为绝对路径...? - Aran-Fey
@DirtyBit 不是。要获取 a.py 的路径,你只需使用 __file__sys.path[0]。但我需要调用者的路径,而不是被调用方法的路径。 - Andrius
如果它没有返回绝对路径,那么是的。我想知道是否将os.path.realpath与组合使用会始终返回正确的绝对路径?因为realpath函数将当前工作目录与相对路径组合在一起。 - Andrius
__file__ 总是一个有效的路径,也就是说,它相对于当前工作目录。 (除非您在代码中更改了CWD,但那就是您自己的问题...) - Aran-Fey
5个回答

5
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更改相对路径或传递整个路径字符串)。谢谢! - Soren V. Raben

1
使用 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

0

你可以使用 Python 中的 os 模块获取它。

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

这将为您提供当前文件的路径,而不是调用者文件的路径。 - Andrius

0
使用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的工作。 - Andrius
print(os.path.abspath("b.py")) - Mikkel Madsen
好的,你仍然需要提供调用者文件名,所以不太好 :) - Andrius

0

技巧在于同时获取当前工作目录相对于该目录与调用者文件(这里是b.py)的路径。使用join方法完成其余部分。

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笔记本上不起作用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接