Динамически создаваемые объекты
Я пытаюсь создать экземпляр объекта из строки. В частности, я пытаюсь изменить это:
from node.mapper import Mapper
mapper = Mapper(file)
mapper.map(src, dst)
во что-то вроде этого:
with open('C:.../node/mapper.py', 'r') as f:
mapping_script = f.read()
eval(mapping_script)
mapper = Mapper(file)
mapper.map(src, dst)
Мотивация для этой, казалось бы, странной задачи, заключается в том, чтобы иметь возможность хранить различные версии сценариев сопоставления в базе данных, а затем извлекать / использовать их по мере необходимости (с акцентом на полиморфизм map()
метод).
Выше не работает. По какой-то причине eval()
бросает SyntaxError: invalid syntax.
Я не понимаю этого, так как это тот же файл, который импортируется в первом случае. Есть ли какая-то причина, почему eval()
нельзя использовать для определения классов?
Я должен отметить, что я знаю о проблемах безопасности вокруг eval()
, Я хотел бы услышать об альтернативных подходах, если таковые имеются. Единственное, о чем я могу думать, - это извлечь скрипт, физически сохранить его в каталоге пакета узла, а затем импортировать, но это кажется еще более безумным.
1 ответ
Вам нужно использовать exec:
exec(mapping_script)
eval()
работает только для выражений. exec()
работает для заявлений. Типичный скрипт Python содержит операторы.
Например:
code = """class Mapper: pass"""
exec(code)
mapper = Mapper()
print(mapper)
Выход:
<__main__.Mapper object at 0x10ae326a0>
Убедитесь, что вы либо позвоните exec()
(Python 3, в Python 2 это утверждение) на уровне модуля. Когда вы вызываете его в функции, вам нужно добавить globals()
, например exec(code, globals())
, чтобы сделать объекты доступными в глобальной области видимости и для остальной части функции, как обсуждено здесь.