使用 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)
我正在尝试从文本文件中读取数据,其中列出了一个变量名并为其赋予了一个值。
例如
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)