0

I have a module Class3.py, with the following code in it:

from common.Step import Step
from StageThree.Class2 import Class2

class Class3(Step):
    pass

I have a logic inside of my project, which will dynamically access this module, and read it in:

module = importlib.import_module(module_name, package_path)

Now, the module variable will hold a dictionary of all information about this module, but I am interested only in grabbing a handle to Class3 from it, for later dynamic instantiation. I sort through that dict with the following code:

dict([(name, cls) for name, cls in module.__dict__.items() if isinstance(cls, type)])

Which yields this result:

{'Step': <class 'common.Step.Step'>, 'Class2': <class 'StageThree.Class2.Class2'>, 'Class3': <class 'StageThree.Class3.Class3'>}

While I know now what classes are present in that module, this still does not help me, because I just want to instantiate a class which was defined in this module (Class3), not imported like Step or Class2.

Any ideas on how I can make Python actually grab only a handle to Class3 in this situation?

UPDATE:

With some ingenuity, I have scrambled together a code which interrogates module for its path, and then reads in file, looks for a line which includes statement "class some_name(" and grabs the name from there. Dirty, but works for now.

available_classes = dict([(name, cls) for name, cls in module.__dict__.items() if isinstance(cls, type)])

with open(module.__file__) as f: 
    declared_classes_names = re.findall(r"class (\w+)\(", " ".join(f.read().splitlines()))

output = []
for class_name in declared_class_names:
    output.append(available_classes[class_name])

Would still be interested to see, if there is any valid way of doing it without brute force approach like above.

1 Answer 1

2

You can check the __module__'s name as well:

import importlib


class ModuleInspector(object):
    def __init__(self):
        self.module = None

    def getClassesInModule(self, localOnly=True):
        """
        localOnly, returns only locally defined classes in that particular module.
        """
        _classes = {}
        for k, v in self.module.__dict__.items():
            if isinstance(v, type):
                if not localOnly or v.__module__ == self.module.__name__:
                    _classes[k] = v
        return _classes

    def importFromFile(self, fpath, name=None):
        try:
            self.module = importlib.import_module(name, fpath)
        except:
            traceback.print_exc()


if __name__ == '__main__':
    i = ModuleInspector()
    i.importFromFile('/tmp/class3.py', 'class3')
    available_classes = i.getClassesInModule(localOnly=False)
    declared_classes_names = i.getClassesInModule()

    print(available_classes)
    print(declared_classes_names)

Output:

{'Queue': <class 'queue.Queue'>, 'scheduler': <class 'sched.scheduler'>, 'Class3': <class 'class3.Class3'>}
{'Class3': <class 'class3.Class3'>}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.