在 Python2 中将 eval 与字典一起使用而不会丢失导入的模块

Use eval with dictionary without losing imported modules in Python2

我的 python 程序中有一个要执行的字符串,我想将字符串中的一些变量(如 x[1]、x[2])更改为其他变量。 我以前使用过带有 2 个参数的 eval(第二个是带有 replaced_word: new_word 的字典),但现在我注意到我不能像这样使用以前导入的模块。所以如果我这样做

from math import log
eval(log(x[1], {x[1]: 1})

它会说它无法识别名称日志。 我怎样才能像这样使用 eval 而不会丢失全局变量? 我真的无法理解文档: https://docs.python.org/2/library/functions.html#eval 所以解释也很有用。

globals() 为基础构建全局变量 dict

from math import log

# Copy the globals() dict so changes don't affect real globals
eval_globals = globals().copy()
# Tweak the copy to add desired new global
eval_globals[x[1]] = 1

# eval using the updated copy
eval('log(x[1])', eval_globals)

或者,您可以使用 three-arg eval 来使用 globals() 未修改的,但也可以提供 locals dict 将首先检查(和修改),在对全球价值观的偏好:

eval('log(x[1])', globals(), {x[1]: 1})

理论上,后一种方法可以让表达式改变原始全局变量,因此添加 .copy() 使其成为 eval('log(x[1])', globals().copy(), {x[1]: 1}) 可以最大限度地降低意外发生的风险。但是 pathological/malicious 代码可以解决这个问题; eval 毕竟是危险的,无论您将其沙盒化到何种程度,都不要相信它的任意输入。