1

I am using this approach to get the current directory of a file:

import pathlib
pathlib.Path(__file__).parent.resolve()

Is it possible to extract this string into a function, that will use the path of the caller? My attempt:

# a.py
import bb.b
print(bb.b.get_current_path(__file__)) # OK: path to a.py directory (.)
print(bb.b.get_current_path()) # WRONG: path to b.py directory (bb)
# bb/b.py
import pathlib
def get_current_path(file=__file__):
    return pathlib.Path(file).parent.resolve()

Is it possible to avoid using __file__ in a.py?

Curious
  • 507
  • 3
  • 16

1 Answers1

1

You can use inspect module to inspect the stack. Though it satisfies the given condition

# bb/b.py
import inspect
import pathlib

stack = inspect.stack()
file_importer = stack[6][1]    

def get_current_path(file=file_importer):
    return pathlib.Path(file).parent.resolve()

I'm not sure if import will be always at the frame with the index 6. Search through code_context can be used instead:

file_importer = next(frameinfo[1] for frameinfo in stack
                     if frameinfo[4] and frameinfo[4][0].startswith('import'))

But this approach breaks the possibility to run b.py, so that exception handling of StopIteration is required with desired behaviour.


Both approaches return the direct importer of b.py, e.g., having a file c.py and calling it from a.py returns the path of c.py

# c.py
import bb.b
get_current_path = bb.b.get_current_path
# a.py
import bb.c
print(bb.c.get_current_path(__file__)) # OK: path to a.py directory (.)
print(bb.c.get_current_path()) # WRONG: path to c.py directory (bb)

Hence, depending on further conditions desired behaviour could be reached by processing inspect.stack().

Vadim Shkaberda
  • 2,807
  • 19
  • 35