检查类名称(字符串)是否用于Python中的某个类

时间:2019-04-03 08:19:39

标签: python python-3.x namespaces metaprogramming

如何获取给定名称下(在当前范围内)可用的确切类变量?我想写一个像这样的函数:

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的确切代码行中可用的所有类(可能在完全不同的模块中,而另一个模块又调用了该模块)。

2 个答案:

答案 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中既没有局部变量也没有内置函数,因此似乎没有很大的潜力注入恶意数据。