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

Check if class name (a string) is used for some class in Python

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

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 提供任何字符串,只要该字符串在调用者的命名空间中作为 class 名称可用,它就会产生正确的 class much就像我将字符串直接复制粘贴到代码中一样。原因是我需要为复杂的对象创建例程提供 class 名称,但尽可能避免使用 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 的确切代码行中可用的所有 classes(它可能在完全不同的模块中,从另一个模块调用)。

您可以将全局字典传递给 my_function。

def my_function(name, g):
    if name in g:
        ...

cls_var = my_function(a, globals())

我想我找到了解决办法。不确定它是否完美,所以我宁愿在接受我自己的回答之前先听听一些评论。

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