如何在python中检查某个类(按字符串名称)是否存在?
是否可以检查某个类是否存在?我在json配置文件中有类名。 我知道我可以简单地尝试通过类名字符串创建一个对象,但这实际上是一个坏主意,因为类构造函数可以做一些意想不到的事情,而此时我只想检查我的配置是否有效,以及所有提到的类是否可用 有什么办法吗如何在python中检查某个类(按字符串名称)是否存在?,python,class,dynamic,Python,Class,Dynamic,是否可以检查某个类是否存在?我在json配置文件中有类名。 我知道我可以简单地尝试通过类名字符串创建一个对象,但这实际上是一个坏主意,因为类构造函数可以做一些意想不到的事情,而此时我只想检查我的配置是否有效,以及所有提到的类是否可用 有什么办法吗 编辑:我也知道你可以从某个模块中获得所有的方法,在我的情况下,我不确定,也不关心方法来自哪个模块。它可以来自任何import语句,我可能不知道它的确切来源。您可以解析源代码以获取所有类名: from ast import ClassDef, parse
编辑:我也知道你可以从某个模块中获得所有的方法,在我的情况下,我不确定,也不关心方法来自哪个模块。它可以来自任何import语句,我可能不知道它的确切来源。您可以解析源代码以获取所有类名:
from ast import ClassDef, parse
import importlib
import inspect
mod = "test"
mod = importlib.import_module(mod)
p = parse(inspect.getsource(mod))
names = [kls.name for kls in p.body if isinstance(kls, ClassDef)]
输入:
class Foo(object):
pass
class Bar(object):
pass
from test2 import Foobar, Barbar, foo
class Foo(object):
pass
class Bar(object):
pass
输出:
['Foo', 'Bar']
['Foobar', 'Barbar', 'Foo', 'Bar']
只需将配置中的类名与返回的名称进行比较
{set of names in config}.difference(names)
如果要包含导入的名称,可以解析导入该名称的模块,但根据导入的方式,仍然可以找到不起作用的情况:
from ast import ClassDef, parse, ImportFrom
import importlib
import inspect
mod = "test"
mod = importlib.import_module(mod)
p = parse(inspect.getsource(mod))
names = []
for node in p.body:
if isinstance(node, ClassDef):
names.append(node.name)
elif isinstance(node, ImportFrom):
names.extend(imp.name for imp in node.names)
print(names)
输入:
class Foo(object):
pass
class Bar(object):
pass
from test2 import Foobar, Barbar, foo
class Foo(object):
pass
class Bar(object):
pass
测试2:
foo = 123
class Foobar(object):
pass
class Barbar(object):
pass
输出:
['Foo', 'Bar']
['Foobar', 'Barbar', 'Foo', 'Bar']
我尝试了,这对我来说很有效,但可能有一种更为类似于python的方法来测试类的存在性:
import types
def class_exist(className):
result = False
try:
result = (eval("type("+className+")") == types.ClassType)
except NameError:
pass
return result
# this is a test class, it's only purpose is pure existence:
class X:
pass
print class_exist('X')
print class_exist('Y')
输出是
True
False
当然,这是一个基本的解决方案,只应与众所周知的输入一起使用:eval
功能是一个很好的后门开启器。有一种更可靠(但也更紧凑)。使用eval()
为任意代码执行打开了大门,为了安全起见,应该避免这种情况
特别是如果你在这里要求解决这样的问题。
那么我们可以假设您对这些风险了解不够
import sys
def str_to_class(str):
return reduce(getattr, str.split("."), sys.modules[__name__])
try:
cls = str_to_class(<json-fragment-here>)
except AttributeError:
cls = None
if cls:
obj = cls(...)
else:
# fight against this
导入系统
def str_至_类(str):
返回reduce(getattr,str.split(“.”),sys.modules[\uu\u name\uu])
尝试:
cls=str_to_class()
除属性错误外:
cls=无
如果是cls:
obj=cls(…)
其他:
#与此抗争
这避免了使用eval
,并得到了多个SO用户的批准。
解决方案类似于。您的意思是,如果一个类正确导入并在命名空间中可用,还是有一个创建了特定名称的类实例?如果您已经导入了所有可用的ObjeTC,您只需检查它即可。您可以编写一个
try-except-namererror
块。关于进一步的信息,我们需要您方面的一些努力。您可以尝试if locals().get('ClassName',False):…
这不是工作的一半吗?如果类存在,它是如何实例化的?谢谢!成功了。它比遍历模块寻找可用类要容易得多。你救了我一天:)只要对任何尝试这个的人说一句话:确保你导入了类本身,而不仅仅是包含它的模块。否则,如果在模块Y中定义类X,检查将失败。我可能应该尝试使用class_exist('Y.X'),但这并不重要。如果您执行“从Y导入X”,您的类将可用,并且测试将正常进行使用eval()
为任意代码执行敞开大门,为了安全起见,应该避免这种情况。@Alexandr使用自己的打印函数injectme()
和class\u exist(“injectme()”
)。当然,攻击者无法轻松创建函数对象。但这应该指出,无意的代码可能会被执行。@wenzul是的,我知道这一点,这就是为什么我问。如果我使用这种方法,我会严格避免对用户输入进行评估。我添加了一个链接到您的解决方案的免责声明。正如我在回答中指出的(我现在必须研究这个)。但也许你的解决方案比问题更一般?同时,您要求的其他信息还没有到达……因为我的项目中的str_to_类方法在一些utils文件中定义,我对它进行了一些修改,以检查类在顶层(从那里调用)是否存在。所以现在它看起来像:def str_to_class(str):frame=inspect.stack()[-1]module=inspect.getmodule(frame[0])返回reduce(getattr,str.split(“.”),sys.modules[module。。。但对于当前的任务,它是好的。。。