I have a single folder ('root') which contains various subfolders and *.py files. 'root' is not a package just a folder with different scripts. I'm trying to find all scripts in 'root' that contain classes that inherit from a specific baseclass. The goal is to present the user with a specific selection of scripts to choose from.
The most obvious way to find subclasses is to use __subclasses__()
which however requires all classes to be loaded (i.e. calling __subclasses__()
on a class will only find those subclasses that are currently loaded), which isn't all that great when you have a folder full of individual scripts.
I tried to search for all *.py files in 'root' and than tried to import them one by one using importlib
, which is not only painfully slow (as you might imagine), I didn't even get it to work properly.
The baseclass is defined as MyBaseClass(with_metaclass(abc.ABCMeta, SomeOtherClass))
I know very little about abc
so I'm not sure if it provides any functionality that could help. (I'm looking into this right now)
Java has a neat Lookup package (http://bits.netbeans.org/7.4/javadoc/org-openide-util-lookup/org/openide/util/Lookup.html) which allows you to tag classes and later lookup all classes with a certain tag. (It usually does its lookup within the confines of a jar, so not exactly the same thing)
My question is: Is there any decent way to get this to work?
EDIT
originally posted as a comment, put here for better visibility:
"Those scripts are different launch scripts & producers for a simulation. They all inherit from 1 of only a few baseclasses. The baseclass can be changed if needed. So I was looking for a way to gather all scripts that inherit from a specific baseclass to present a choice of specific scripts."
The code I currently use to crawl a directory and import all *.py files:
def all_files(directory):
for path, dirs, files in os.walk(directory):
for f in files:
if f.endswith('.py'):
yield os.path.join(path, f)
# Found here:
# https://stackoverflow.com/questions/3137731/is-this-correct-way-to-import-python-scripts-residing-in-arbitrary-folders
def import_from_absolute_path(fullpath, global_name=None):
script_dir, filename = os.path.split(fullpath)
script, ext = os.path.splitext(filename)
sys.path.insert(0, script_dir)
try:
module = __import__(script)
if global_name is None:
global_name = script
globals()[global_name] = module
sys.modules[global_name] = module
except ModuleNotFoundError as mnf:
print(mnf)
except ImportError as ie:
print(ie)
except FileNotFoundError as fnf:
print(fnf)
finally:
del sys.path[0]