Reputation: 1828
I'm attempting to instantiate an object from a string. Specifically, I'm trying to change this:
from node.mapper import Mapper
mapper = Mapper(file)
mapper.map(src, dst)
into something like this:
with open('C:.../node/mapper.py', 'r') as f:
mapping_script = f.read()
eval(mapping_script)
mapper = Mapper(file)
mapper.map(src, dst)
The motivation for this seemingly bizarre task is to be able to store different versions of mapping scripts in a database and then retrieve/use them as needed (with emphasis on the polymorphism of the map()
method).
The above does not work. For some reason, eval()
throws SyntaxError: invalid syntax.
I don't understand this since it's the same file that's being imported in the first case. Is there some reason why eval()
cannot be used to define classes?
I should note that I am aware of the security concerns around eval()
. I would love to hear of alternative approaches if there are any. The only other thing I can think of is to fetch the script, physically save it into the node package directory, and then import it, but that seems even crazier.
Upvotes: 2
Views: 116
Reputation: 85442
You need to use exec:
exec(mapping_script)
eval()
works only for expressions. exec()
works for statements. A typical Python script contains statements.
For example:
code = """class Mapper: pass"""
exec(code)
mapper = Mapper()
print(mapper)
Output:
<__main__.Mapper object at 0x10ae326a0>
Make sure you either call exec()
(Python 3, in Python 2 it is a statement) at the module level. When you call it in a function, you need to add globals()
, for example exec(code, globals())
, to make the objects available in the global scope and to the rest of the function as discussed here.
Upvotes: 1