1

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'
1
  • You probably want a break once you've found the target_class Commented Nov 14, 2012 at 16:17

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

3 Comments

Are you getting ImportError or AttributeError?
AttributeError: 'module' object has no attribute 'MyClass'
Ahh so the key was to separate the ImportError and AttributeError into separate try statements. Now it works, thanks!
1

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>

Comments

0

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!'

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.