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

Is using exec() to execute code read from a text file bad practice?

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

例如

manufacturer_num = 12345

我想将此数据存储到已经初始化的 class 变量中。 class 变量的名称与文本文件中的变量相同。在这种情况下使用 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)

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

exec可以执行任意代码。最重要的问题是你是否总是暗中信任输入文件?答案应该是 no,除非您曾经对您个人正在生成的数据使用此代码一次。

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

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

(由于显而易见的原因,我没有实际测试这个。)

即使您将自己的代码用于您个人生成的数据,但在未来,您可能会因为代码编写的格式错误的输入文件而伤害自己。

假设您的数据格式保持不变,并且不深入研究您如何使用 class 变量,下面是我编写代码的方式。

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)