Mike
Mike

Reputation: 60771

Python, import string of Python code as module

In python you can do something like this to import a module using a string filename, and assign its namespace a variable on the local namespace.

x = __import__(str)

I'm wondering if there is a related function that will take take a string of Python code, instead of a path to a file with Python code, and return its namespace as a variable.

For example,

str = "a = 5";
x = importstr(str)
print x.a
#output is 5

I realize that I could write the string to a file, then use __import__ on it, but I'd like to skip the intermediate file if possible.

The reason for this is that I'm experimenting with metaprogramming in python, and it seems like a good solution to what I'm doing.

Upvotes: 21

Views: 12623

Answers (5)

LVitya
LVitya

Reputation: 567

types.ModuleType is not recommended according to Python documentation on module_from_spec():

importlib.util.module_from_spec(spec)

...

This function 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.

Here is what I came up with to load the module from source code.

import importlib.util
spec = importlib.util.spec_from_loader('helper', loader=None)
helper = importlib.util.module_from_spec(spec)
exec('a = 5', helper.__dict__)

print(type(helper)) # prints "<class 'module'>"
helper.a # prints "5"

Upvotes: 6

kirbyfan64sos
kirbyfan64sos

Reputation: 10727

Unfortunately, the imp module was recently deprecated (I have NO idea why).

Instead, you should do this:

from types import ModuleType
import sys

mod = ModuleType('my_module', 'doc string here')
exec('a = 1', mod.__dict__)
print(mod.a) # prints 1
# add to sys.modules
sys.modules['my_module'] = mod

Or you can use PyExt's RuntimeModule.from_string:

from pyext import RuntimeModule

mod = RuntimeModule.from_string('a = 1')
print(mod.a) # 1

Upvotes: 8

Remi
Remi

Reputation: 21175

Here is how to import a string as a module:

import sys,imp

my_code = 'a = 5'
mymodule = imp.new_module('mymodule')
exec my_code in mymodule.__dict__    

so you can now access the module attributes (and functions, classes etc) as:

mymodule.a
>>> 5

To ignore any next attempt to import, add the module to sys:

sys.modules['mymodule'] = mymodule

Upvotes: 6

Jeremy Brown
Jeremy Brown

Reputation: 18318

Here's an example of dynamically creating module objects using the imp module

Upvotes: 15

Tarantula
Tarantula

Reputation: 19862

Is this something what you're looking for ?

my_namespace = {}
exec "a = 5" in my_namespace
print my_namespace["a"]

Upvotes: 2

Related Questions