Использование exec () для выполнения кода, читаемого из текстового файла, - плохая практика? - PullRequest
2 голосов
/ 09 июля 2019

Я пытаюсь прочитать данные из текстового файла, в котором указано имя переменной и ей дано значение.

например,

manufacturer_num = 12345

Я хочу сохранить эти данныев уже инициализированные переменные класса.Имена переменных класса совпадают с переменными в текстовом файле.Является ли плохой практикой использование exec () в этом случае, и есть ли лучший способ сделать это?

Ниже приведен код, который у меня есть в настоящее время.Текстовый файл очень длинный.

 def initialize(self):
        f = open(self.path, "r")
        for x in range(self.init_var_len):
            line = f.readline()
            if "=" in line:
                split_string = line.split("=")
                split_string[0] = split_string[0].strip()
                split_string[1] = split_string[1].strip()
                exec("self." + split_string[0] + "=" + "type(self." + split_string[0] + ")(" + "'"+split_string[1]+"'"+")")

        f.close()

        for each in self.__dict__.keys():
            print eval("self." + each)

1 Ответ

0 голосов
/ 09 июля 2019

YES.Использование exec является плохой практикой.

exec может выполнить произвольный код.Самый важный вопрос: всегда ли вы неявно доверяете входным файлам?Ответ должен быть нет , если вы не используете этот код один раз для данных, которые вы лично производите прямо сейчас.

Ниже приведен пример входного файла, который ваш код будет читать изатем немедленно удалите весь жесткий диск.

manufacturer_num = 12345'); import os; os.system('rm -rf /

(По очевидным причинам я не проверял это на самом деле.)

Даже если вы используете свой код для данных, которые вы лично производите, но вВ будущем вы рискуете навредить себе искаженным исходным файлом, который вы написали для наполовину запомненного кода.

Предполагая, что ваш формат данных остается прежним, и без погружения в то, как вы используете переменные класса, вот как я бы написалкод.

def initialize(self):
    with open(self.path, "r") as f:
        for x, line in enumerate(f):
            line = line.strip()
            if not line:
                continue  # Skip blank lines
            name, value = [s.strip() for s in line.split("=", maxsplit=1)]
            if '=' in value:
                raise ValueError(
                    f'Unexpected multiple "=" in line {x}: {line}')
            # Initialization depends on self.path. Don't let the file
            # overwrite it. Also, limit ourselves to class variables
            # because, hopefully, they're declared explicitly in the
            # code, and the OP said class variables.
            cls = type(self)
            if not hasattr(cls, name) or name == 'path':
                raise AttributeError(name)
            expected_type = type(getattr(cls, name))
            setattr(self, name, expected_type(value))
    # vars is the canonical way of accessing self.__dict__
    for name, value in vars(self).items():
        print(name, value)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...