如何用Python动态创建本体类?JSON转本体类报错求助
问题描述
尝试将包含随机字典数据的JSON文件转换为本体类,需要动态创建类,但运行代码时触发错误。
代码示例
attributs_data = data.get("attributs", {}) # 提取JSON中的attributs数据 if isinstance(attributs_data, dict): attributs = Attributs() document.has_attributs = attributs for key, value in attributs_data.items(): prop_name = f"has_{key}" # 在本体上下文内定义动态属性 with onto: # 根据值的类型创建对应类 if isinstance(value, str): prop_cls = types.new_class(prop_name, (FunctionalProperty,), kwds={"domain": [Attributs], "range": [str]}) elif isinstance(value, dict): nested_cls = types.new_class(key.replace(" ", "_").capitalize(), (Thing,)) nested_instance = nested_cls() setattr(attributs, prop_name, nested_instance) for subkey, subvalue in value.items(): nested_prop_name = f"has_{subkey}" with onto: if isinstance(subvalue, str): nested_prop_cls = types.new_class(nested_prop_name, (FunctionalProperty,), kwds={"domain": [nested_cls], "range": [str]}) elif isinstance(subvalue, int): nested_prop_cls = types.new_class(nested_prop_name, (FunctionalProperty,), kwds={"domain": [nested_cls], "range": [int]}) elif isinstance(subvalue, float): nested_prop_cls = types.new_class(nested_prop_name, (FunctionalProperty,), kwds={"domain": [nested_cls], "range": [float]}) elif isinstance(subvalue, bool): nested_prop_cls = types.new_class(nested_prop_name, (FunctionalProperty,), kwds={"domain": [nested_cls], "range": [bool]}) setattr(nested_instance, nested_prop_name, subvalue)
错误信息
File "jsonToOwl.py", line 115, in <module> prop_cls = types.new_class(prop_name, (FunctionalProperty,), ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3.12/types.py", line 74, in new_class return meta(name, resolved_bases, ns, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: EntityClass.__new__() got an unexpected keyword argument 'domain'
解决思路
这个错误的核心是错误地通过types.new_class的kwds参数传递domain、range属性——本体框架(如Owlready2)的EntityClass构造函数不支持这种传参方式。正确做法是先创建属性类,再手动设置这些属性。
修正步骤
- 调用
types.new_class时,只传入类名和父类,不传递kwds参数 - 在
with onto:上下文内,给新创建的属性类手动赋值domain和range
以字符串类型属性的创建为例,修正后的代码:
if isinstance(value, str): # 先创建属性类,仅指定类名和父类 prop_cls = types.new_class(prop_name, (FunctionalProperty,)) # 手动设置domain和range prop_cls.domain = [Attributs] prop_cls.range = [str]
嵌套属性的创建同理,比如处理子字典中的整数属性:
elif isinstance(subvalue, int): nested_prop_cls = types.new_class(nested_prop_name, (FunctionalProperty,)) nested_prop_cls.domain = [nested_cls] nested_prop_cls.range = [int]
额外注意事项
- 确保
Attributs、Thing、FunctionalProperty等类来自你使用的本体库,且已正确关联到onto实例 - 所有动态类的创建操作必须在
with onto:上下文内执行,否则类不会被注册到本体中
内容的提问来源于stack exchange,提问作者pleijan
相关产品推荐
相关产品推荐

