I have a directory filled with an arbitrary number of modules, each of which contains only a function do_stuff
. For example:
foos/
__init__.py
foo_1.py
foo_2.py
...
foo_n.py
foo_1.py, for example, could just be:
def do_stuff(bar):
if bar.blah:
return True
return False
From elsewhere in the code, I want to collect and run all the do_stuff
functions. I though this would be easy with the imp
module:
import imp
...
...
FOOS_DIR = os.path.join(MY_HOME, 'foos/')
MOD_REGEX = r'^(?!__).*\.py$'
foos = [imp.load_source(fname.split('.py')[0], FOOS_DIR)
for fname in os.listdir(FOOS_DIR)
if re.match(MOD_REGEX, fname)]
results = [foo.do_stuff('argument!') for foo in foos]
However, this leads to:
AttributeError: "'module' object has no attribute 'do_stuff'"
From the top answer here, I thought this was the way to go. If it is, maybe my syntax is off? After all, load_source
is really forgiving:
(pdb) imp.load_source('not_there', FOOS_DIR)
<module 'not_there' from '/home/blah/blah/foos'>
Otherwise, what could I be missing?
It is indeed a syntax issue! I need the full path to the module file, not just its directory, as the second argument to load_source
:
Thus,
foos = [imp.load_source(fname.split('.py')[0], FOOS_DIR)
for fname in os.listdir(FOOS_DIR)
if re.match(MOD_REGEX, fname)]
Becomes
foos = [imp.load_source(fname.split('.py')[0], '%s%s' % (FOOS_DIR, fname))
for fname in os.listdir(FOOS_DIR)
if re.match(MOD_REGEX, fname)]
And it works just fine!