首页 > 解决方案 > 如何将由其他地方定义的函数和变量构建的表达式传递给 exec() 或 eval()?

问题描述

我有一个项目需要在多个位置进行部署。每个位置的代码都必须相同,并在配置文件中定义自定义。大多数配置文件将是整数字典,但在某些情况下,表达式将包含代码中定义的函数。我eval()用来解释包含这些表达式的文本,但我遇到了与范围相关的问题。我的第一次尝试包括以下代码行

temp_text="np.round(get_last_3_values_avg(data,'Qty',sku),decimals=0)"
new_val=eval(temp_text,globals())

其中get_last_3_values_avg和变量在别处定义。此代码产生一个错误,指出变量未定义。我也试过

ex_st='def tempfun():\n\treturn '+temp_text
exec(ex_st)
a =tempfun

但这会产生相同的错误。我也尝试在文本字符串中定义一个变量而不是一个函数,但得到了相同的结果:

ex_st='var='+temp_text
exec(ex_st)
a =var

另一种尝试是尝试在 locals 字典中检索该函数:

ex_st='def tempfun():\n\treturn '+temp_text
loca={}
exec(ex_st,globals(),loca)
a = loca['tempfun']

但我得到的是函数而不是函数返回的值。我也尝试将变量传递给函数。为了解决这个问题,我尝试了一个 lambda 函数:

def outer(data,sku):
    return lambda q: loca['tempfun'](data,sku)
temp=outer(data,sku)

wheretempfun被修改为采用变量,但我遇到了同样的问题。有没有办法将一行代码读取为带有 exec 或 eval 的字符串,该字符串中的文本引用其他地方定义的变量和函数?我还应该提到,代码将在只有合格工程师才能访问的计算机上本地运行,因此有关安全问题的担忧eval()很小。谢谢

标签: pythonscopeexecevalglobal

解决方案


我同意配置文件中的允许代码很尴尬,应该更改,但我想说明问题的解决方案已经实现,以防其他人有同样的问题。解决方案是将代码嵌入到问题中所述的函数中:

ex_st='def tempfun():\n\treturn '+temp_text
loca={}
exec(ex_st,globals(),loca)
a = loca['tempfun']

然后正如 juanpa.arrivilla 解释的那样:

desired_value=a()

如果 tempfun() 需要访问任何变量,则可能需要将它们作为参数输入添加到函数中。我必须将所有可能的变量添加到函数中,并让它使用 temp_text 中调用的变量。这很尴尬。我使用的解决方案是允许配置文件中的值是一个字典,它指定数据的位置,也是一个字符串值,确定数据应该如何处理(函数读取的关键字)作为所有的键在模块中而不是在配置中处理数据。谢谢您的帮助!


推荐阅读