bzrr
bzrr

Reputation: 1530

Get path of script containing the calling function

Say I have two files, foo.py and bar.py. It does not matter where they are located, only that foo.py somehow manages to import bar.py and call a function func() defined in the latter. How would I get the absolute path of foo.py from bar.func()?

Upvotes: 6

Views: 2879

Answers (3)

martineau
martineau

Reputation: 123403

I'm not sure what you mean by "get the absolute path of foo.py from bar.func()". However, it's possible for a function to determine whose calling it at runtime by using sys._getframe() to reach back through the call stack and examine the calling function's globals (the variable namespace in the code below). Here's an example showing how to do that:

foo.py

import bar

bar.func()

bar.py

from pprint import pprint
import sys

def func():
    namespace = sys._getframe(1).f_globals  # caller's globals
    pprint(namespace)
    print("caller's path:", namespace['__file__'])

Sample output:

{'__annotations__': {},
 '__builtins__': <module 'builtins' (built-in)>,
 '__cached__': None,
 '__doc__': None,
 '__file__': '\\Stack Overflow\\get-path-of-calling-script\\foo.py',
 '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x0085A7D0>,
 '__name__': '__main__',
 '__package__': None,
 '__spec__': None,
 'bar': <module 'bar' from '\\Stack Overflow\\get-path-of-calling-script\\bar.py'>,
 'sys': <module 'sys' (built-in)>}
caller's path: \Stack Overflow\get-path-of-calling-script\foo.py

See the '__file__' entry in the returned dictionary? It's the absolute path to the source file — foo.py — that contained the call made to bar.func().

Upvotes: 7

Mahir Islam
Mahir Islam

Reputation: 1972

To get the absolute path, you can also try this:

import os
print(os.path.abspath("foo.py"))

Upvotes: 0

Gelineau
Gelineau

Reputation: 2090

In func, you can use inspect:

def func():
    stack = inspect.stack()
    calling_context = next(context for context in stack if context.filename != __file__)
    print(calling_context.filename)

Edited: I just saw jasonharper's comment that proposes the same solution. Read also abarnet's comment.

Upvotes: 1

Related Questions