在eval中修改Python全局变量

在eval中修改Python全局变量,python,eval,Python,Eval,我有这样的代码: globals_defined = {'add': my_add_fn, 'divide': my_divide_fn} eval_result = eval(<some code>, {data: {'name_1': 'NAME1', 'name_2': 'NAME2'}, globals_defined) 编辑:我应该先添加这个。是的,我需要使用eval。此评估最初来自用户输入,但已解析为一个抽象语法树,该树拒绝除少数数学运算以外的所有运算。然后,AST是通

我有这样的代码:

globals_defined = {'add': my_add_fn, 'divide': my_divide_fn}
eval_result = eval(<some code>, {data: {'name_1': 'NAME1', 'name_2': 'NAME2'}, globals_defined)
编辑:我应该先添加这个。是的,我需要使用eval。此评估最初来自用户输入,但已解析为一个抽象语法树,该树拒绝除少数数学运算以外的所有运算。然后,AST是通过定义一些自定义函数定义来评估的


不过,听起来我不能这样做。

您不应该首先使用eval。 但是,由于您没有显示您在其中运行的代码,因此没有办法建议替代方案

事实上,Python的
eval
只执行表达式——Python中的赋值是
语句
——通常情况下,在eval中不能有赋值

解决这个问题的方法就是使用
exec
而不是eval。默认情况下,
exec
将使用运行它的模块的全局变量,因此,执行代码中的任何赋值都将影响全局命名空间

如果您将字典作为第二个参数传递给
exec
,它将使用该字典作为其全局字典,然后您可以让它使用赋值修改该dict中的值

这是关于eval和exec的一般性陈述-您的具体问题是(可能)试图调用eval内部的函数-
add()
-该函数在
globals\u定义的
字典中公开。问题是您的add函数是在模块中定义的,超出了eval(或exec)范围。
my\u add\u fn
函数的全局变量不是传递给eval的
globals
,而是模块globals本身。因此,它访问的变量
count\u iterations
在模块范围内,而不是在
globals\u定义的
字典内

当然有办法解决这个问题。最好的方法是:不要使用eval(或exec)。 最后一行的print习惯用法表明您是Python新手,否则您将了解现有的强大的字符串格式化方法。 也就是说:您可以调用存储在字典中的函数,就像访问字典中的任何元素一样,即:
globals\u defined[“add”]()
将使用您的所有
my\u add\u fn
功能-这是一个如何避免使用“eval”的提示

最后,回到您的问题所在——解决问题的一种方法是让您的函数不依赖于其全局名称空间,而是接收和返回参数——然后在exec字符串范围外对函数返回的值进行赋值——因此:

def my_add_fn(count):
   return 'blah!', count+1

global_dict = {"add": my_add_fn, "count_iterations": 0} 

exec("result, count_iterations = add()", global_dict)

print "Count = {}".format(global_dict["count_iterations"])

为什么要尝试使用全局名称空间?为什么不构造一个特定的本地名称空间来将函数传递给
eval
?将
globals()?你想解决什么问题?我也不能这样做,因为会有多个评估正在运行?将多个eval更改为多个exec。相反,将代码更改为不使用eval动态调用所需函数。:-)他/她实际上并没有这样做——他/她正在传递一本自定义词典。相反,问题在于调用一个试图更改全局变量的函数——但函数的全局变量不是传递给eval的全局变量。
def my_add_fn():
   global count_iterations
   count_terations += 1
   return 'blah!'
def my_add_fn(count):
   return 'blah!', count+1

global_dict = {"add": my_add_fn, "count_iterations": 0} 

exec("result, count_iterations = add()", global_dict)

print "Count = {}".format(global_dict["count_iterations"])