How to get only user defined classes in Python /PyQt5?

Question:

My aim is to get the user-defined classes only. Try the following things, But I get all classes. So pls suggest, how to get the user-defined classes only instead of all classes. In my case, iterates/loops approx 200 times for each file( I need only the first three items class A, Class B and Class C only). How to get the user-defined classes only.

File : identify_user_defined_class

import importlib
import inspect

file_list =["identify_user_defined_class_base"]
list_class =[]
dict_class = {}

aa = 0

for items in file_list:
    module_name = importlib.import_module(items)

    for class_name,class_obj in inspect.getmembers(module_name):
        aa = aa+1
        print("bbbbb", aa,class_name,class_obj)
        if inspect.isclass(class_obj) and str(class_obj)[0:12] != "<class 'PyQt":
            source, start_line = inspect.getsourcelines(class_obj)
            list_class.append([start_line,class_name])
            dict_class.update({class_name:class_obj})
    list_class.sort()

File : identify_user_defined_class_base

from PyQt5.QtWidgets import *

class A(QWidget):
    pass

class B(QWidget):
    pass

class C(QWidget):
    pass
Asked By: Bala

||

Answers:

The simple solution is to compare the __module__ attribute of the class with the name of the imported module. This attribute specifies the module in which the class is defined, so it is sufficient to distinguish it from all other imported or built-in classes.

Thus, in your example, you can simply do:

if inspect.isclass(class_obj) and class_obj.__module__ == items:
    ...

However, although this might be good enough for your immediate use-case, it isn’t a particularly robust solution. One obvious problem with it, is that it doesn’t handle sub-classes very well. For example, consider a module like this:

from PyQt5.QtWidgets import QWidget

class BaseClass(QWidget):
    def commomMethod(self):
        ...

class ClassA(BaseClass):
    ...

class ClassB(ClassA):
    ...

For your use-case, I presume you would want to include ClassA and ClassB, but not BaseClass. However, not allowing this very common form of subclassing would probably be too restrictive for a system like this. So the usual solution is to define a special base-class that explicitly marks the classes you want to import. This would mean the above module would look like this:

from PyQt5.QtWidgets import QWidget
from mymodule import MarkerClass

class BaseClass(QWidget): ...
class ClassA(BaseClass, MarkerClass): ...
class ClassB(ClassA): ...

And your importer code would then look like this:

from mymodule import MarkerClass
...

if (inspect.isclass(class_obj) and class_obj is not MarkerClass and
    issubclass(class_obj, MarkerClass)):
    ...

where MarkerClass can just be an empty class definition, like this:

class MarkerClass: pass

This approach will be much more robust and easier to maintain in the long-run, and allows for much greater flexibility when designing the dynamically imported classes.

Answered By: ekhumoro

Try it

for items in file_list:
    module_name = importlib.import_module(items)
    dict_class.update([class_item for class_item in inspect.getmembers(module_name, inspect.isclass) if class_item[1].__module__ == items])
Answered By: Kumar