Использование Eval в Python для создания переменных класса
-
16-09-2019 - |
Вопрос
Я написал класс, который позволяет мне передавать список типов переменных, имен переменных, подсказок и значений по умолчанию.Класс создает панель wxPython, которая отображается во фрейме, позволяющем пользователю устанавливать входные значения перед нажатием кнопки рассчитать и получением результатов обратно в виде графика.Я добавляю все переменные в класс, используя инструкции exec .Это позволяет объединить все переменные в одном классе, и я могу ссылаться на них по имени.
light = Variables( frame , [ ['f','wavelength','Wavelength (nm)',632.8] ,\
['f','n','Index of Refraction',1.0],])
Внутри класса я создаю и устанавливаю переменные со статментами типа:
for variable in self.variable_list:
var_type,var_text_ctrl,var_name = variable
if var_type == 'f' :
exec( 'self.' + var_name + ' = ' + var_text_ctrl.GetValue() )
Когда мне нужно использовать переменные, я могу просто ссылаться на них по имени:
wl = light.wavelength
n = light.n
Затем я читаю дальше, так что редко возникает необходимость использовать exec в Python.Есть ли проблема с таким подходом?Есть ли лучший способ создать класс, который содержит переменные, которые следует сгруппировать вместе, которые вы хотите иметь возможность редактировать, а также имеет вызовы code и wxPython для отображения, редактирования (а также сохранения всех переменных в файл или их повторного чтения)?
Курт
Решение
Вы можете использовать setattr
функция, которая принимает три аргумента:объект, имя атрибута и его значение.Например,
setattr(self, 'wavelength', wavelength_val)
эквивалентно:
self.wavelength = wavelength_val
Итак, вы могли бы сделать что-то вроде этого:
for variable in self.variable_list:
var_type,var_text_ctrl,var_name = variable
if var_type == 'f' :
setattr(self, var_name, var_text_ctrl.GetValue())
Другие советы
Я согласен с ответом мипади, но хотел добавить еще один ответ, поскольку в Исходном сообщении спрашивалось, есть ли проблема с использованием exec.Я хотел бы обратиться к этому вопросу.
Думай как преступник.
Если бы ваш злонамеренный противник знал, что у вас есть код, который гласит:
exec( 'self.' + var_name + ' = ' + var_text_ctrl.GetValue() )
затем он или она может попытаться ввести значения для var_name и var_text_ctrl, которые взломают ваш код.
Представьте, мог бы злоумышленник присвоить var_name это значение:
var_name = """ a = 1 # some bogus assignment to complete "self." statement import os # malicious code starts here os.rmdir('/bin') # do some evil # end it with another var_name # ("a" alone, on the next line) a """
Внезапно злоумышленник смог заставить ВАС выполнить [ute] код для удаления вашего каталога / bin (или любого другого зла, которое они хотят).Теперь ваше заявление exec примерно соответствует эквиваленту:
exec ("self.a=1 \n import os \n os.rmdir('/bin') \n\n " "a" + ' = ' + var_text_ctrl.GetValue() )
нехорошо!!!
Как вы можете себе представить, при использовании exec возможно создавать всевозможные инъекции вредоносного кода.Это возлагает на разработчика обязанность думать о любом способе взлома кода - и добавляет ненужный риск, когда доступна безрисковая альтернатива.
Для тех, кто заботится о безопасности, может существовать приемлемая альтернатива.Раньше существовал модуль вызова rexec, который допускал "ограниченное" выполнение произвольного кода python.Этот модуль был удален из последних версий python. http://pypi.python.org/pypi/RestrictedPython это еще одна реализация сотрудников Zope, которая создает "ограниченную" среду для произвольного кода python.
Модуль был удален из-за проблем с безопасностью.Очень сложно обеспечить среду, в которой любой код может быть выполнен в ограниченной среде, со всем тем самоанализом, который есть у Python.
Лучше всего избегать eval и exec .
Действительно нестандартная идея - использовать Google App Engine и позволить им беспокоиться о вредоносном коде.