【问题标题】:Check if class name (a string) is used for some class in Python检查类名(字符串)是否用于 Python 中的某些类
【发布时间】:2019-04-03 08:19:39
【问题描述】:

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

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 的确切代码行中可用的所有类(它可能位于从另一个模块调用的完全不同的模块内)。

【问题讨论】:

  • 你想从全局范围返回类还是类的属性?
  • 两者都不是,否则globals()getattr 将起作用。它是其他一些类,在任意位置定义,但在调用命名空间中可用。

标签: python python-3.x namespaces metaprogramming


【解决方案1】:

您可以将全局 dict 传递给 my_function。

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

cls_var = my_function(a, globals())

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 2016-08-09
      • 2020-11-01
      • 2014-05-07
      • 2018-05-01
      • 2010-11-22
      • 2011-03-31
      • 1970-01-01
      • 2015-03-15
      相关资源
      最近更新 更多