Динамически создаваемые объекты

Я пытаюсь создать экземпляр объекта из строки. В частности, я пытаюсь изменить это:

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()), чтобы сделать объекты доступными в глобальной области видимости и для остальной части функции, как обсуждено здесь.

Другие вопросы по тегам