I have the following bizarre set up. Consider 3 scripts in different directories:
- root1/folderA/scriptA.py
- root2/folderB/scriptB.py
- root2/folderC/scriptC.py
The first file and it's location are fully modifiable. The second and third are completely fixed.
scriptA.py contains a parent class:
class A:
def get_path(self):
# ...
# code to determine "my_path"
# ...
return my_path
scriptB.py contains a child class:
from root1.folderA.scriptA import A
class B(A):
pass
scriptC.py contains the code to execute:
from root2.folderB.scriptB import B
if __name__ == "__main__":
b = B()
print(b.get_path()) # want print root/folderB/scriptB.py
In scriptC.py what I want is the behaviour to get the path of the child class's declaration file (without any hard-coding). Is there any way to program the A.get_path()
to have this behavoir?
I've tried looking into the inspect
, os.path
and pathlib
modules but I haven't had any luck.
CodePudding user response:
It looks like the trick is to use __init_subclass__
which runs whenever a class is sub-classed, in conjunction with a class's __module__
attribute to retrieve its containing module, and __file__
to retrieve the absolute path to the python script or module.
For example, in script_a.py
:
import sys
from pathlib import Path
class PathInfo:
__slots__ = ()
path: Path
def __init_subclass__(cls, **kwargs):
mod = sys.modules[cls.__module__]
# `__file__` is a string, so we want to convert to a `Path` so it's easier to work with
cls.path = Path(mod.__file__)
class A(PathInfo):
__slots__ = ()
script_b.py
:
from script_a import A
class B(A):
pass
# prints: /Users/<name>/PycharmProjects/my-project/script_a.py
print(A().path)
# prints: /Users/<name>/PycharmProjects/my-project/script_b.py
print(B.path)