如何获取给定名称下(在当前范围内)可用的确切类变量?我想写一个像这样的函数:
from my_module import ClassA # A subclass of my_other_module.BenevolentClass
from my_other_module import my_function
a = 'ClassA'
cls_var = my_function(a)
o = cls_var()
因此,我可以向my_function提供任何字符串,只要该字符串在调用者的名称空间中作为类名可用,它就会产生正确的类,就像我将字符串直接复制到代码中一样。原因是我需要为复杂的对象创建例程提供类名,但是在可能的情况下避免使用eval
。我当前的实现是这样的:
def my_function(name):
if name in globals():
c = globals()[name]
# Actually a complex class whitelist
if issubclass(c, BenevolentClass):
return c
else:
raise ValueError(f'Potentially malicious class {name}')
但是,这显然是从my_other_module生成globals()的,这不是我想要的。我想要在调用my_function
的确切代码行中可用的所有类(可能在完全不同的模块中,而另一个模块又调用了该模块)。
答案 0 :(得分:0)
您可以将全局字典传递给my_function。
def my_function(name, g):
if name in g:
...
cls_var = my_function(a, globals())
答案 1 :(得分:0)
我想我已经找到了解决方案。不确定它是否完美,因此在接受自己的答案之前,我宁愿听一些评论。
import inspect
def my_function(name):
for frame in inspect.getouterframes(inspect.currentframe()):
c = None
if name in frame.frame.f_globals:
c = frame.frame.f_globals[name]
break
if c and issubclass(c, BenevolentClass):
return c
else:
raise ValueError(f'Potentially malicious class {name}')
据我了解,inspect.getouterframes
沿调用堆栈向外移动,我可以检查每一步的全局变量以了解可用的内容。 frame.f_globals
中既没有局部变量也没有内置函数,因此似乎没有很大的潜力注入恶意数据。