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()

Tags:

Python