Skip to content

Instantly share code, notes, and snippets.

@Dbof
Created September 29, 2019 11:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dbof/c7df34806cbbda2f94ca119db97b2e70 to your computer and use it in GitHub Desktop.
Save Dbof/c7df34806cbbda2f94ca119db97b2e70 to your computer and use it in GitHub Desktop.
Script to find and load classes from a specific directory
import os
import inspect
import logging
from importlib.machinery import SourceFileLoader
import pkg_resources
logger = logging.getLogger(__name__)
# Search in "project/modules/"
SEARCH_PATHS = [pkg_resources.resource_filename("project", "modules")]
def search(base):
"""
Search subclasses of class 'base' and return a list.
"""
class_list = set()
class_list_modules = set() # for preventing module reload
for path in SEARCH_PATHS:
logger.debug('Entering path \'{}\''.format(path))
for root, d, files in os.walk(path):
# search for files with .py extension
candidates = [fname for fname in files if fname.endswith('.py') and
not fname.startswith('__')]
classes = []
for c in candidates:
# get filename
modname = os.path.splitext(c)[0]
try:
if modname in class_list_modules:
# module already loaded
continue
# load class into current Python env
module = SourceFileLoader(
modname,
os.path.join(root, c)).load_module()
# add loaded module to set
class_list_modules.add(modname)
logger.debug('Loaded module \'{}\''.format(modname))
except (SystemError, ImportError,
NotImplementedError, SyntaxError) as e:
logger.debug(e)
logger.warn(f'Module could not be loaded: {modname}')
continue
# enumerate classes found in module
for cls in dir(module):
# for every class, get the actual "class" object" for checks
cls = getattr(module, cls)
# if class is a class and is part of the module
# and is a subclass of argument base (but not the base itself)
if (inspect.isclass(cls) and
inspect.getmodule(cls) == module and
issubclass(cls, base) and
cls != base):
logger.info('Class found in {f}'.format(f=module))
# found
classes.append(cls)
class_list.update(classes)
logger.debug('Imported modules: {}'.format(str(class_list_modules)))
logger.debug('Returned class list: {}'.format(str(class_list)))
return list(class_list)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment