This function allows you to do "from module import name", where both "module" and "name" are dynamic values (i.e. expressions or variables). For example, this can be used to implement a "plugin" mechanism to extend an application by external modules that adhere to some common interface.
This pattern is used in MoinMoin (http://moin.sourceforge.net/) to load extensions implementing variations of a common interface, like "action", "macro", and "formatter".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
def importName(modulename, name): """ Import a named object from a module in the context of this function, which means you should use fully qualified module paths. Return None on failure. """ try: module = __import__(modulename, globals(), locals(), [name]) except ImportError: return None return vars(module)[name] ### MyApp/extensions/spam.py class Handler: def handleSomething(self): print "spam!" ### MyApp/extensions/eggs.py class Handler: def handleSomething(self): print "eggs!" ### Example extension_name = "spam" # could be "eggs", too! Handler = importName("MyApp.extensions." + extension_name, "Handler") handler = Handler() handler.handleSomething()
Don't forget to have __init__.py. Since this module uses a __import__ call, the extensions folder will have to have an __init__.py in it so that python treats the directory as module path.
Improve it. Could you perhaps expand this recipe to allow either all, or multiple/selected names to be imported, for example,
to import all names, and
to import selected names.
Also, it would be nice if the names did not have to be assigned manually, i.e., instead of
one could do, for instance, simply
and 'func', 'func2', 'func3', and 'class' would all be imported as attributes of 'module'.
hmm, no, wait...
If the second argument is NOT given it should just import module with all the attributes: 'module.func', 'module.func2', 'module.func3', 'module.class', and if the second argument IS given, it should import all the names into the global scope: 'func', 'func2', 'func3', 'class'.