Say I have a function foo(). When invoked, I want that function to reliably determine the file path of the module (or the calling function) that invoked it. The issue is that various functions in the inspect module only return relative paths (relative to the working directory at the time of import, I assume). However, my code switches working directories multiple times and I don't know the working directory in question.
import inspect
import os
def foo():
frame = inspect.stack()[0]
print(frame.filename)
print(os.path.abspath(frame.filename))
foo()
os.chdir("/")
print("New CWD:", os.getcwd())
foo()
Output:
$ cd ~
$ python3 foo.py
foo.py
/home/user/foo.py
New CWD: /
foo.py
/foo.py
Through auto-completion in my IDE I discovered that there's an undocumented function inspect.getabsfile(). Unfortunately, that doesn't work reliably, either:
import inspect
def foo():
print("Hello")
print(inspect.getabsfile(foo))
os.chdir("/")
print("New CWD:", os.getcwd())
print(inspect.getabsfile(foo))
Output:
$ cd ~
$ python3 foo.py
/home/user/foo.py
New CWD: /
/foo.py
If I understand this bug report correctly, __file__ and code.co_filename (docs) were (are?) going to become absolute paths at some point that hasn't happened (yet). What can I do to solve this issue in the meantime?
Update: Turns out the main issue with the above two example scripts is that they access objects / stack frames originating in the main module. As soon as one imports an object from a different module or considers the stack frame of a function living in another module, it works. In a similar way, in other modules than __main__, __file__ indeed gives absolute path. (See also this issue in the Python bug tracker.) I'm at a loss as to why the main module is being treated differently, though.