Reputation: 32061
I want to dynamically load a class from a given string. However, I do not know which file the class will be in, so I will have to search all files. I've tried this, but I get AttributeError: 'module' object has no attribute 'MyClass'
even though I'm 100% sure that that module (in the current iteration) has that class:
target = 'MyClass'
module_names = [mf[0:-3] for mf in os.listdir('application/models') if mf.endswith(".py")]
modules = [imp.new_module(x) for x in module_names]
for module in modules:
try:
target_class = getattr(module, target)
except ImportError, AttributeError:
continue
if target_class:
print 'found class'
It seems I'm getting really close. What I want is not to limit the search to just one folder, but perhaps multiple folders. What's wrong with my code?
Edit: Ok now I'm trying something like this, but still getting the same error:
for m in module_names:
try:
x = reload(__import__(m))
target_class = getattr(x, target)
except ImportError, AttributeError:
continue
else:
break
if target_class:
print 'found class'
Upvotes: 1
Views: 3166
Reputation: 1
Following the example in the imp documentation:
File in same directory named hello.py:
def myFunction():
return "Hello World!"
Import hello dynamically (w/o try except finally):
fp, pathname, description = imp.find_module("hello")
hello = imp.load_module("hello", fp, pathname, description)
hello.myFunction() # returns 'Hello World!'
Upvotes: 0
Reputation: 17312
According to the documentation new_module
returns and empty module:
imp.new_module(name)
Return a new empty module object called name. This object is not inserted in sys.modules.
You may want to look at imp.load_source instead. This is just a simple example:
class Test:
pass
And
In [19]: m = imp.load_source("test", "./test.py")
In [20]: getattr(m, "Test")
Out[20]: <class test.Test at 0x1fe6120>
Upvotes: 1
Reputation: 309891
From the documentation on imp.new_module
, the returned module is empty. Meaning that it will never contain your class.
Perhaps what you want to do is add your target directory to sys.path
and use __import__
to dynamically import those modules, then check for your class?
The following code works for me:
modules = ['foo','bar']
for mod in modules:
try:
x = reload(__import__(mod))
except ImportError:
print "bargh! import error!"
continue
try:
cls = getattr(x,'qux')
except AttributeError:
continue
a = cls()
print a.__class__.__name__
Where foo.py
and bar.py
are in the same directory:
#foo.py
class foo(object):
pass
and:
#bar.py
class qux(object):
pass
Upvotes: 2