Python:我应该使用eval、exec还是其他?

4 投票
4 回答
1948 浏览
提问于 2025-04-16 11:56

我正在尝试让下面的语句变得更灵活:

for posting in page.findAll(attrs = {"id": re.compile(r'''post\d+''')}):

这部分内容是从一个CSV文件中动态获取的,并存储在一个字符串里(比如叫做test的字符串)。这个CSV文件存放在一个安全的地方,只有管理员可以访问。

attrs = {"id": re.compile(r'''post\d+''')}

我可以通过使用eval(test)或exec(test)来整合这个变量,而不是仅仅使用test吗?

for posting in page.findAll(test)):

4 个回答

1

最安全的方法是 ast.literal_eval()

>>> args = ast.literal_eval('{"a":1}')
>>> args
{'a': 1}

你可以这样使用它:

some_function_or_method(**args)
1

如果你对CSV文件的来源完全没有控制权,那就尽量避免使用这些加载方式。

  • 使用pickle模块把正则表达式保存为序列化的数据(或者更简单点,直接保存成字符串就行)
  • 使用json模块把数据保存为JSON格式
  • csv模块把数据写入文件

然后,要从文件中获取数据时,就反过来做。

如果你无法控制CSV的生成,试着用split或者re模块手动提取数据。

evalexec是“最后的解决方案”。除非没有其他办法,否则尽量不要使用它们。

5

如果你想运行用户输入的代码(比如文件内容),你需要用到 evalexec 这类东西,特别是 exec 用于执行语句(赋值就是一种语句)。

不过,你其实不应该这样做,因为这样做很危险、不安全,而且完全没有必要。你可以省去赋值的部分(只保存字典),然后用 ast.literal_eval 来处理,这样就安全多了(当然,你还是需要处理语法错误和其他可能出错的情况,以便显示一个合理的错误信息,但恶意代码几乎不可能执行,而且这样做也干净多了)。如果你觉得有必要的话,可以在加载后再使用 re.compile

撰写回答