如何将未知的局部变量传递给其他命名空间

时间:2015-09-08 11:59:46

标签: python python-3.4

我想读一些输入,其中包含python赋值语句,如此字符串:

"VARIABLE = 'something' + OTHER_VAR"

所以我使用其中一个:

exec("VARIABLE = 'something' + OTHER_VAR")
exec("VARIABLE = 'something' + OTHER_VAR", globals(), locals())

我想在其他代码中使用此变量,但在exec(...)之后它不在当前命名空间中。 可以像这样得到变量值:

locals()['VARIABLE']

然而,如果我不知道变量的名称,那对我来说不是解决方案。

那么如何将新变量放入我的命名空间?

更新 我的exec数据是这样的:

COMPBLOCK =  StringLeft(MyPlatform.HierarchicalName,6) +"_IADI." + CMP + "." + BLOCK ;
SetCustomPropertyValue("DEVLM2",COMPBLOCK + ".DEVLM2",false);
SetCustomPropertyValue("CRIT",COMPBLOCK + ".CRIT",false);
SetCustomPropertyValue("UNACK",COMPBLOCK + ".UNACK",false);
SetCustomPropertyValue("ALMSTA_26",COMPBLOCK + ".ALMSTA#B26",false);

我定义了函数SetCustomPropertyValueStringLeft。我希望避免使用所有可能的输入将此脚本复杂地转换为python。 Exec()似乎是非常快速的解决方案,但在阅读this post - Modifying locals in python后,我有点陷入困境。

2 个答案:

答案 0 :(得分:1)

  1. 注意有关从外国来源执行任意代码有多危险的警告。
  2. 如果语句具有一致的格式,例如示例中的格式,则可以轻松解析它并提取变量名称:

    varname = stmt.split('=')[0].strip()
    

    或使用正则表达式更复杂的东西

  3. 如果语句总是只引入一个新变量,您可以在执行前后比较locals()并检查添加了哪个新变量:

    old_locals = set(locals().keys())
    exec(stmt)
    new_locals = set(locals().keys())
    varname = (new_locals-old_locals).pop()
    

答案 1 :(得分:0)

如何使用configparser中的小域特定语言来声明新变量? 这样您就不需要运行不受信任的代码,并且可以获得变量扩展等简单的东西(尽管语法略有不同)。

E.g。考虑以下输入

FOO = world
BAR = hello, @FOO@

简单的解析器可能如下所示:

lines=["FOO = world", "BAR = hello, @FOO@" ]
vars={}

# store variables in dictionary, with expansion
for line in lines:
  key, value = [x.strip() for x in line.split('=', 1)]
  for k in vars:
     value=value.replace('@%s@' % (k), str(vars[k]))
  vars[key]=value
# make variables available in local namespace
for k in vars:
    locals()[k]=vars[k]
## use new variable
print(BAR)