I have some code in the form of a string and would like to make a module out of it without writing to disk.
When I try using imp and a StringIO object to do this, I get:
>>> imp.load_source('my_module', '', StringIO('print "hello world"')) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: load_source() argument 3 must be file, not instance >>> imp.load_module('my_module', StringIO('print "hello world"'), '', ('', '', 0)) Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: load_module arg#2 should be a file or None
How can I create the module without having an actual file? Alternatively, how can I wrap a StringIO in a file without writing to disk?
UPDATE:
NOTE: This issue is also a problem in python3.
The code I'm trying to load is only partially trusted. I've gone through it with ast and determined that it doesn't import anything or do anything I don't like, but I don't trust it enough to run it when I have local variables running around that could get modified, and I don't trust my own code to stay out of the way of the code I'm trying to import.
I created an empty module that only contains the following:
def load(code): # Delete all local variables globals()['code'] = code del locals()['code'] # Run the code exec(globals()['code']) # Delete any global variables we've added del globals()['load'] del globals()['code'] # Copy k so we can use it if 'k' in locals(): globals()['k'] = locals()['k'] del locals()['k'] # Copy the rest of the variables for k in locals().keys(): globals()[k] = locals()[k]
Then you can import mymodule
and call mymodule.load(code)
. This works for me because I've ensured that the code I'm loading does not use globals
. Also, the global
keyword is only a parser directive and can't refer to anything outside of the exec.
This really is way too much work to import
the module without writing to disk, but if you ever want to do this, I believe it's the best way.
To load the default version of Python module, use module load python . To select a particular software version, use module load python/version . For example, use module load python/3.5 to load the latest version of Python 3.5. After the module is loaded, you can run the interpreter by using the command python .
You need to use the import keyword along with the desired module name. When interpreter comes across an import statement, it imports the module to your current program. You can use the functions inside a module by using a dot(.) operator along with the module name.
Importing Modules To make use of the functions in a module, you'll need to import the module with an import statement. An import statement is made up of the import keyword along with the name of the module. In a Python file, this will be declared at the top of the code, under any shebang lines or general comments.
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 the short solution from schlenk using types.ModuleType is still working in python 3.7
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 my_name = 'my_module' my_spec = importlib.util.spec_from_loader(my_name, loader=None) my_module = importlib.util.module_from_spec(my_spec) my_code = ''' def f(): print('f says hello') ''' exec(my_code, my_module.__dict__) sys.modules['my_module'] = my_module my_module.f()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With