使用exec()执行从文本文件中读取的代码是一种不好的做法吗?

时间:2019-07-08 22:40:09

标签: python exec

我正在尝试从文本文件中读取数据,该文件中列出了变量名并为其赋了值。

例如

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 :(得分:0)

是。使用exec是不好的做法。

exec可以执行任意代码。最重要的问题是您是否始终隐式信任输入文件?答案应该是no,除非您一次对自己现在正在生成的数据使用此代码。

以下是输入文件的示例,您的代码将读取该输入文件,然后立即删除整个硬盘驱动器。

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)