Soskii Soskii - 2 months ago 9
Python Question

Is there a version of __file__ that when used in a function, will get the name of the file that uses the library?

So, as a joke I wrote a version of goto for python that I wanted to use as a library. The function I wrote for it is as follows.

def goto(loc):
exec(open(__file__).read().split("# "+str(loc))[1],globals())
quit()


This works for cases where it is in the file where goto is used, such as this:

def goto(loc):
exec(open(__file__).read().split("# "+str(loc))[1],globals())
quit()


# hi
print("test")
goto("hi")


However, if I import goto in another file, it doesn't work as

__file__


will always return the file with the function in it, not the one it is used in. Is there an equivalent of file that will allow me to import a file with the goto function in it and have it work?

Answer

Yes, you can if you inspect the call stack:

import inspect

def goto():
    try:
        frame = inspect.currentframe()
        print(frame.f_back.f_globals['__file__'])
    finally:
        # break reference cycles
        # https://docs.python.org/3.6/library/inspect.html#the-interpreter-stack
        del frame

goto()

Note that the call stack is actually python implementation dependent -- So for some python interpreters, this might not actually work...

Of course, I've also shown you how to get the caller's globals (locals can be found via frame.f_back.f_locals for all of your execing needs).

Also note that it looks like you can implement a jump command by writing to the frame's f_lineno -- which might be a better way to implement your goto. I've never done this though so I can't really advise you on how to actually code it up :-)