Recipe 16.3. Importing from a Module Whose Name Is Determined at RuntimeCredit: Jürgen Hermann ProblemYou need to import a name from a module, just as from module import name would do, but module and name are runtime-computed expressions. This need often arises, for example, when you want to support user-written plug-ins. SolutionThe _ _import_ _ built-in function lets you perform this task: def importName(modulename, name): """ Import a named object from a module in the context of this function. """ try: module = _ _import_ _(modulename, globals( ), locals( ), [name]) except ImportError: return None return getattr(module, name) DiscussionThis recipe's function lets you perform the equivalent of from module import name, in which either or both module and name are dynamic values (i.e., expressions or variables) rather than constant strings. For example, this functionality can be used to implement a plug-in mechanism to extend an application with external modules that adhere to a common interface. Some programmers' instinctive reaction to this task would be to use exec, but this instinct would be a pretty bad one. The exec statement is too powerful, and therefore is a last-ditch measure, to be used only when nothing else is available (which is almost never). It's just too easy to have horrid bugs and/or security weaknesses where exec is used. In almost all cases, there are better ways. This recipe shows one such way for an important problem. For example, suppose you have, in a file named MyApp/extensions/spam.py, the following code: class Handler(object): def handleSomething(self): print "spam!" and, in a file named MyApp/extensions/eggs.py: class Handler(object): def handleSomething(self): print "eggs!" We must also suppose that the MyApp directory is in a directory on sys.path, and both it and the extensions subdirectory are identified as Python packages (meaning that each of them must contain a file, possibly empty, named _ _init_ _.py). Then, we can get and call both implementations with the following code: for extname in 'spam', 'eggs': HandlerClass = importName("MyApp.extensions." + extname, "Handler") handler = HandlerClass( ) handler.handleSomething( ) It's possible to remove the constraints about sys.path and _ _init_ _.py, and dynamically import from anywhere, with the imp standard module. However, imp is substantially harder to use than the _ _import_ _ built-in function, and you can generally arrange things to avoid imp's greater generality and difficulty. The import pattern implemented by this recipe is used in MoinMoin (http://moin.sourceforge.net/) to load extensions implementing variations of a common interface, such as action, macro, and formatter. See AlsoDocumentation on the _ _import_ _ and getattr built-ins in the Library Reference and Python in a Nutshell; MoinMoin is available at http://moin.sourceforge.net. |