How to load a module from code in a string?
Here is how to import a string as a module (Python 2.x):
import sys,imp
my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec my_code in mymodule.__dict__
In Python 3, exec is a function, so this should work:
import sys,imp
my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec(my_code, mymodule.__dict__)
Now access the module attributes (and functions, classes etc) as:
print(mymodule.a)
>>> 5
To ignore any next attempt to import, add the module to sys
:
sys.modules['mymodule'] = mymodule
imp.new_module
is deprecated since python 3.4, but it still works as of python 3.9
imp.new_module
was replaced with importlib.util.module_from_spec
importlib.util.module_from_spec is preferred over using
types.ModuleType
to create a new module as spec is used to set as many import-controlled attributes on the module as possible.importlib.util.spec_from_loader uses available loader APIs, such as
InspectLoader.is_package()
, to fill in any missing information on the spec.
these module attributes are __builtins__
__doc__
__loader__
__name__
__package__
__spec__
import sys, importlib.util
def import_module_from_string(name: str, source: str):
"""
Import module from source string.
Example use:
import_module_from_string("m", "f = lambda: print('hello')")
m.f()
"""
spec = importlib.util.spec_from_loader(name, loader=None)
module = importlib.util.module_from_spec(spec)
exec(source, module.__dict__)
sys.modules[name] = module
globals()[name] = module
# demo
# note: "if True:" allows to indent the source string
import_module_from_string('hello_module', '''if True:
def hello():
print('hello')
''')
hello_module.hello()