Reputation: 1530
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
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
Reputation: 1972
To get the absolute path, you can also try this:
import os
print(os.path.abspath("foo.py"))
Upvotes: 0
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