我需要获取所有符号的名称列表,以便评估或执行一段代码。我试图使用symtable
模块,但似乎它没有正确处理lambdas和内部函数(def
s在其他代码中)。考虑一下:
import symtable
symtable.symtable("x+y", '<string>', 'exec').get_symbols()
我明白了:[<symbol 'y'>, <symbol 'x'>]
这正是我所期待的。
但是当我写这篇文章时:
symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec').get_symbols()
结果是:[<symbol 'z'>]
我没有关于x
(没关系,它是一个局部变量)的信息,也没有y
(这是全局的,这就是我需要的)
但是,当我尝试使用exec("z=lambda x: x+y; z(10)")
对此进行评估时,y
的值丢失了。有没有办法可以识别必须提供给表达式或代码的所有符号的名称,以便可以对其进行评估/执行?
答案 0 :(得分:0)
没有多少...我需要查看子符号表。递归是首选工具:
import symtable
def find_global_symbols(table):
symbols = set()
for t in table.get_children():
symbols |= find_global_symbols(t)
symbols |= set(s.get_name() for s in table.get_symbols() if s.is_global())
return symbols
table = symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec')
global_symbols = find_global_symbols(table)
这给了我y
作为答案。这就是我需要的。现在我知道我必须提供y
的值才能执行相关代码。
更新:如果我考虑在每个范围内导入的名称,实际上可能会有改进
def find_global_symbols(table, imports):
imports = imports | set(s.get_name() for s in table.get_symbols() if s.is_imported())
symbols = set()
for s in table.get_symbols():
if s.is_global() and s.get_name() not in imports:
symbols.add(s.get_name())
for t in table.get_children():
symbols |= find_global_symbols(t, imports)
return symbols
table = symtable.symtable("z=lambda x: x+y; z(10)", '<string>', 'exec')
global_symbols = find_global_symbols(table, set())