Reputation: 11337
In Python, I have a string of some Python source code containing functions like:
mySrc = '''
def foo():
print("foo")
def bar():
print("bar")
'''
I'd like to compile this string into some kind of module-like object so I can call the functions contained in the code.
Here's pseudo-code for what I'd like to do:
myMod = myCompile(mySrc)
myMod.foo()
Is this possible in Python? I've tried this, but it does not work:
myMod = compile(mySrc, '', 'exec')
myMod.foo()
This produces an error message like this:
<code object <module> at 0x104154730, file "", line 1>Traceback (most recent call last):
File "myfile.py", line XX, in run
myMod.foo()
AttributeError: 'code' object has no attribute 'foo'
Upvotes: 18
Views: 8255
Reputation: 13140
In Python 2, you want the magical compiler package:
>>> import compiler
>>> mod = compiler.parseFile("doublelib.py")
>>> mod
Module('This is an example module.\n\nThis is the docstring.\n',
Stmt([Function(None, 'double', ['x'], [], 0,
'Return twice the argument',
Stmt([Return(Mul((Name('x'), Const(2))))]))]))
>>> from compiler.ast import *
>>> Module('This is an example module.\n\nThis is the docstring.\n',
... Stmt([Function(None, 'double', ['x'], [], 0,
... 'Return twice the argument',
... Stmt([Return(Mul((Name('x'), Const(2))))]))]))
Module('This is an example module.\n\nThis is the docstring.\n',
Stmt([Function(None, 'double', ['x'], [], 0,
'Return twice the argument',
Stmt([Return(Mul((Name('x'), Const(2))))]))]))
>>> mod.doc
'This is an example module.\n\nThis is the docstring.\n'
>>> for node in mod.node.nodes:
... print node
...
Function(None, 'double', ['x'], [], 0, 'Return twice the argument',
Stmt([Return(Mul((Name('x'), Const(2))))]))
>>> func = mod.node.nodes[0]
>>> func.code
Stmt([Return(Mul((Name('x'), Const(2))))])
And in Python 3, it's built right in.
Upvotes: 1
Reputation: 224942
You have to both compile and execute it:
myMod = compile(mySrc, '', 'exec')
exec(myMod)
foo()
You can pass dicts to exec
to stop foo
from “leaking” out. Combine it with a module object created using types.ModuleType
:
from types import ModuleType
…
compiled = compile(mySrc, '', 'exec')
module = ModuleType("testmodule")
exec(compiled, module.__dict__)
Upvotes: 28