Recipe 16.2. Importing a Dynamically Generated Module
Credit: Anders Hammarquist
Problem
You need to wrap code in either
compiled or source form in a module, possibly adding it to
sys.modules as well.
Solution
We build a new module object, optionally add it to
sys.modules, and populate it with an
exec statement:
import new
def importCode(code, name, add_to_sys_modules=False):
"" code can be any object containing code: a string, a file object, or
a compiled code object. Returns a new module object initialized
by dynamically importing the given code, and optionally adds it
to sys.modules under the given name.
""
module = new.module(name)
if add_to_sys_modules:
import sys
sys.modules[name] = module
exec code in module._ _dict_ _
return module
Discussion
This recipe lets you import a module from code that is dynamically
generated or obtained. My original intent for it was to import a
module stored in a database, but it will work for modules from any
source. Thanks to the flexibility of the exec
statement, the importCode function can accept code
in many forms: a string of source (which gets implicitly compiled on
the fly), a file object (ditto), or a previously compiled code
object.The addition of the newly generated module to
sys.modules is optional. You
shouldn't normally do so for such dynamically
obtained code, but there are exceptionsspecifically, when
import statements for the
module's name are later executed, and
it's important that they retrieve from
sys.modules your dynamically generated module. If
you want the sys.modules addition,
it's best to perform it before the
module's code body executes, just as normal import
statements do, in case the code body relies on that normal behavior
(which it usually doesn't, but it
can't hurt to be prepared).Note that the normal Python statement:
import fooin simple cases (where no hooks, built-in modules, imports from zip
files, etc., come into play!) is essentially equivalent to:
if 'foo' in sys.modules:A toy example of using this recipe:
foo = sys.modules['foo']
else:
foofile = open("/path/to/foo.py") # for some suitable /path/to/...
foo = importCode(foofile, "foo", 1)
code = ""
def testFunc( ):
print "spam!"
class testClass(object):
def testMethod(self):
print "eggs!"
""
m = importCode(code, "test")
m.testFunc( )
o = m.testClass( )
o.testMethod( )
See Also
Sections on the import and exec
statements in the Language Reference;
documentation on the modules attribute of the
sys standard library module and the
new module in the Library
Reference; Python in a Nutshell
sections about both the language and library aspects.