pyshacl无法验证并序列化新推断图问题求助
pyshacl执行SPARQL Construct规则无输出排查
我在用pyshacl(Python的RDF图与SHACL验证库)时遇到问题:SHACL规则图中的SPARQL Construct子句本该创建新实例并关联现有实例,生成包含新数据的图,但验证返回成功后却没有任何输出实例;相同的SPARQL查询在GraphDB查询编辑器中能得到预期结果。
相关代码
from rdflib import * from pyshacl import validate ontology = Graph().parse("./graphs/DMN-RDF-Dicon-OCQA-Tbox.ttl", format="ttl") example_building = Graph().parse("./graphs/Duplex_A_20110505_LBD.ttl", format="ttl") combined_graph = ontology + example_building # 合并本体与实例图 rules_graph = Graph().parse("testing.ttl", format="ttl") # 加载SHACL规则图 # 执行验证并应用规则 conforms, inferred_graph, string = validate(combined_graph, shacl_graph=rules_graph, data_graph_format='turtle', shacl_graph_format='turtle', debug=True, advanced=True, inplace=True) # 合并原始图与推断图 new_graph = combined_graph + inferred_graph # 序列化新图 new_graph.serialize( destination="Inferred_geometry_inspections.ttl", format="ttl")
SHACL规则图(省略部分前缀)
{prefixes} dmn:prepare_inspections a sh:NodeShape ; sh:targetNode owl:Thing ; sh:rule [ a sh:SPARQLRule ; sh:comment "Select all of eligible objects and create inspections"; sh:construct """ {prefixes} CONSTRUCT { ?this ocqa:hasInspection ?Inspection_Number_Of_Risers. ?Inspection_Number_Of_Risers a <http://www.DMN-RDF.org/DMN#Inspection_Number_Of_Risers>. ?ISCode a <http://www.DMN-RDF.org/DMN#ISCode>. ?Agent a <https://w3id.org/digitalconstruction/0.5/Agents#Agent>. ?InspectionEquipment a <https://w3id.org/ocqa#InspectionEquipment>. ?one_time a <http://www.DMN-RDF.org/DMN#one_time>. ?Location a <https://w3id.org/digitalconstruction/0.5/Entities#Location>. ?InspectionProcedure a <https://w3id.org/ocqa#InspectionProcedure>. } WHERE{ SELECT ?this ?Inspection_Number_Of_Risers ?ISCode ?Agent ?InspectionEquipment ?one_time ?Location ?InspectionProcedure WHERE { BIND(IRI(CONCAT("inst:Inspection_Number_Of_Risers_", STR(CEIL((RAND() * 30000))))) as ?Inspection_Number_Of_Risers) BIND(IRI(CONCAT("inst:ISCode_", STR(CEIL((RAND() * 30000))))) as ?ISCode) BIND(IRI(CONCAT("inst:Agent_", STR(CEIL((RAND() * 30000))))) as ?Agent) BIND(IRI(CONCAT("inst:InspectionEquipment_", STR(CEIL((RAND() * 30000))))) as ?InspectionEquipment) BIND(IRI(CONCAT("inst:one_time_", STR(CEIL((RAND() * 30000))))) as ?one_time) BIND(IRI(CONCAT("inst:Location_", STR(CEIL((RAND() * 30000))))) as ?Location) BIND(IRI(CONCAT("inst:InspectionProcedure_", STR(CEIL((RAND() * 30000))))) as ?InspectionProcedure) ?this a <https://pi.pauwel.be/voc/buildingelement#Stair> . ?Property a <https://w3id.org/opm#Property> . ?this <http://lbd.arch.rwth-aachen.de/props#actualNumberOfRisers> ?Property . } } """ ; ] ; .
排查与解决方法
1. 修正inplace=True参数的误用
代码中设置了inplace=True,这会让pyshacl直接将推断结果写入原始的combined_graph,导致inferred_graph为空。后续合并空图等于没有添加新数据。
- 解决:要么移除
inplace=True(默认值为False),让inferred_graph接收推断结果;要么直接序列化combined_graph,无需再合并inferred_graph。
修改后的验证代码示例:
conforms, inferred_graph, string = validate( combined_graph, shacl_graph=rules_graph, data_graph_format='turtle', shacl_graph_format='turtle', debug=True, advanced=True )
2. 检查数据匹配条件
规则的WHERE子句仅匹配https://pi.pauwel.be/voc/buildingelement#Stair类型且带有actualNumberOfRisers属性的实例,需确认:
combined_graph中确实存在符合条件的实例- IRI拼写、大小写完全一致(比如本体中的类IRI是否和规则中的完全匹配)
- 可以单独用rdflib查询
combined_graph,验证是否能返回预期的?this实例:
query = """ SELECT ?this WHERE { ?this a <https://pi.pauwel.be/voc/buildingelement#Stair> . ?this <http://lbd.arch.rwth-aachen.de/props#actualNumberOfRisers> ?p . } """ results = combined_graph.query(query) print([row for row in results]) # 查看是否有结果
3. 显式定义SPARQL Construct中的前缀
规则中用{prefixes}占位符,但pyshacl对SPARQL规则内的前缀解析可能依赖显式定义。建议在Construct字符串开头直接写出所有用到的前缀,避免依赖外部前缀:
sh:construct """ @prefix dmn: <http://www.DMN-RDF.org/DMN#> . @prefix ocqa: <https://w3id.org/ocqa#> . @prefix inst: <http://example.org/inst/> . @prefix dc-agents: <https://w3id.org/digitalconstruction/0.5/Agents#> . @prefix dc-entities: <https://w3id.org/digitalconstruction/0.5/Entities#> . CONSTRUCT { ?this ocqa:hasInspection ?Inspection_Number_Of_Risers. ?Inspection_Number_Of_Risers a dmn:Inspection_Number_Of_Risers. ?ISCode a dmn:ISCode. ?Agent a dc-agents:Agent. ?InspectionEquipment a ocqa:InspectionEquipment. ?one_time a dmn:one_time. ?Location a dc-entities:Location. ?InspectionProcedure a ocqa:InspectionProcedure. } ... """ ;
4. 测试随机数函数兼容性
虽然GraphDB支持RAND(),但rdflib的SPARQL引擎对部分函数的支持可能有差异。可以先把随机数替换为固定值测试,看是否能生成实例:
BIND(IRI("inst:Inspection_Number_Of_Risers_123") as ?Inspection_Number_Of_Risers) BIND(IRI("inst:ISCode_456") as ?ISCode) # 其他BIND同理
5. 查看debug日志定位问题
代码中开启了debug=True,运行时会输出详细日志,重点关注:
- 规则是否被触发(日志中会显示
Applying rule...相关内容) - SPARQL查询是否返回结果(日志中会显示查询的结果行数)
- 是否有前缀解析错误或IRI绑定异常
内容的提问来源于stack exchange,提问作者Kuladeep
相关产品推荐
相关产品推荐

