简体   繁体   中英

Get caller function's absolute path to its file?

If there is method t1 in file a.py and there is a file b.py , which calls method t1 from a.py file. How do I get full/absolute path to b.py file inside t1 method?

With inspect module (just like here: how to get the caller's filename, method name in python ), I can get relative path to file, but it seems it does not contain absolute path (or there is some other attribute object, to access to get it?).

As an example:

a.py:

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

b.py:

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

Using 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`

Hence :

py -m a2.py

OUTPUT :

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

EDIT :

Using 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`

OUTPUT :

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

You can get it with the os module in python.

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

Using the os module you can do the following:

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`

With this, you could call t1(__file__ and get the absolute path for any file.

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

Running from another module:

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

Prints:

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

The trick consists in recovering both the current working directory and the relative path wrt that directory to the caller file (here b.py ). The join does the rest.

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`

The trick does not work for jupyter notebooks unfortunately..

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM