SlideShare una empresa de Scribd logo
2
Lo más leído
5
Lo más leído
10
Lo más leído
Rdflib
From ZERO to HERO in an hour
Daniel Fernández Álvarez
fernandezalvdaniel@uniovi.es
I got it… I think
Rdflib es…
• Librería para manejo de RDF:
• Parseo y serialización
• Múltiples formatos: N-triples, turtle, rdf/XML, JSON-LD (con plug-in)…
• Modelo de grafo en memoria:
• Creación
• Modificación
• Consulta (interfaz SPARQL)
• Soporte a quads (named graphs).
• Lenguajes de programación:
• Python
• Posible utilizarlo en R
Rdflib no es …
• …un triplestore*:
• Verdaderos triplestores: Virtuoso, BlazeGraph, Neptune…
• … apta para BigData*:
• Contenido del grafo cargado en memoria.
• … una librería para lanzar consultas contra endpoints:
• sparqlwrapper, de los los mismos desarrolladores, sí sirve para ello.
* Puede ser utilizada junto con algunas bases de datos (ej: Berkeley DB)
para hacer su contenido persistente…
… pero si necesitas eso, usa un triplestore ;)
Parsear un grafo
Local, remoto, string
from rdflib import Graph
# Local graph
g = Graph()
g.parse("example.ttl", # param 'source'
format="turtle")
# Remote graph
g = Graph()
g.parse("https://raw.githubusercontent.com/DaniFdezAlvarez/"
"shexerp3/develop/test/t_files/t_graph_1.ttl",
format="turtle")
# Graph in a 'str' object
dumb_g_str = "<http://ex.org/Asturias> <http://ex.org/capital>
<http://ex.org/Oviedo> ."
g = Graph()
g.parse(data=dumb_g_str,
format="nt")
• Parámetro source:
• Fichero local o
remoto
• Parámetro data:
• str
• Parámetro format:
• Fundamental
(rdflib no adivina
sintaxis)
• Rdf/xml por
defecto.
Parsear un grafo
Local, string
• Parámetro
destination:
• Fichero local
• Por defecto, None
• Si destination es
None, retorna objeto
‘bytes’
• Convertir ‘bytes’ a
‘str’ con decode()
• Parámetro format:
• Rdf/xml por defecto.
• No adivina formato
por la extensión
especificada.
g = Graph()
g.parse("example.ttl",
format="turtle")
g.serialize(destination="example_out.nt", # To local file
format="nt")
str_g = g.serialize(format="nt") # If 'destination' is None
# (deftault value), the content
# is returned as a bytes object
print(str_g)
print(type(str_g)) # type(str_g) --> 'bytes'
str_g = str_g.decode("utf-8")
print(str_g) # type(str_g) --> 'str'
print(type(str_g))
Modificar/crear grafo
• Cada tripleta es una 3-tupla de Python.
• Tuplas: conjuntos ordenados e inmutables.
• Las tripletas se componen de objetos de modelo de rdflib:
• URI  rdflib.URIRef
• Literal  rdflib.Literal
• Nodo anónimo  rdflib.BNode
• Añadir una tripleta a un grafo g:
• g.add( a_triple ) # type(a_triple) == ‘tuple’
Modelo Rdflib: URIs
• URIRef
• Representa cualquier entidad con una URI (clases, instancias, propiedades).
• Instancias de URIRef usando constructor:
• Instancias de URIRef usando rdflib.Namespace:
• Rdflib incluye algunos namespaces preconstruidos: RDF, RDFS, OWL, XSD.
• Aconsejable: hacer binding del namespace.
• Asocia un prefijo reconocible a cierto namespace al serializar.
URIRef("http://example.org/Labra")
example = Namespace("http://example.org/")
labra = example.Labra
example = Namespace("http://example.org/")
g.bind("ex", example)
Modelo Rdflib: literales
• Literal:
• Representa cualquier tipo de literal.
• Instancias con constructor.
• Parámetros:
• value: valor del literal.
• datatype (opcional): tipo de dato, especificado en forma de URI (URIRef).
• lang(opcional): añade una etiqueta de lenguaje al literal (en, es…).
• Especificación de datatype:
• Si no se rellena datatype, rdflib es capaz de mapear el type() de value con los
elementos más comunes de XSD.
• CONSEJO: su mapeo puede no ser perfecto. Si se puede conocer el tipo a priori, usar un
datatype explícito.
Modelo Rdflib: nodos anónimos
• BNode:
• Representa nodos anónimos (Blank Nodes).
• Instancias con constructor:
• En general, sin parámetros. Puedes especificar un id para tu BNode con el parámetro
value si el contexto lo requiere.
• Cuando operes con un nodo anónimo, recuerda guardar un puntero al objeto
BNode instanciado para poder referenciarlo desde diferentes tripletas.
apple_anonymous = BNode()
g.add((example.Labra, example.holds, apple_anonymous))
g.add((apple_anonymous, RDF.type, example.Apple))
g.add((apple_anonymous, example.color, example.Green))
Modelo Rdflib: tripletas
from rdflib import Graph, URIRef, Literal, BNode, Namespace, RDF, XSD
g = Graph()
example = Namespace("http://example.org/")
g.bind("ex", example)
foaf = Namespace("http://xmlns.com/foaf/0.1/")
g.bind("foaf", foaf)
a_triple = (example.Labra, RDF.type, foaf.Person)
g.add(a_triple)
g.add( (URIRef("http://example.org/Labra"), foaf.ageString, Literal("31", lang="es") ) )
g.add( (example.Labra, foaf.age, Literal(31) ) )
g.add( (example.Labra, foaf.ageFloat, Literal("31", datatype=XSD.float) ) )
apple_anonymous = BNode()
g.add((example.Labra, example.holds, apple_anonymous))
g.add((apple_anonymous, RDF.type, example.Apple))
g.add((apple_anonymous, example.color, example.Green))
g.add((apple_anonymous, example.isTasty, Literal(True)))
print(g.serialize(format="turtle").decode("utf-8"))
Efecto de bind
@prefix ex: <http://example.org/> .
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:Labra a foaf:Person ;
ex:holds [ a ex:Apple ;
ex:color ex:Green ;
ex:isTasty true ] ;
foaf:age 31 ;
foaf:ageFloat "31.0"^^xsd:float ;
foaf:ageString "31"@es .
@prefix ns1: <http://example.org/> .
@prefix ns2: <http://xmlns.com/foaf/0.1/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix xml: <http://www.w3.org/XML/1998/namespace> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ns1:Labra a ns2:Person ;
ns1:holds [ a ns1:Apple ;
ns1:color ns1:Green ;
ns1:isTasty true ] ;
ns2:age 31 ;
ns2:ageFloat "31.0"^^xsd:float ;
ns2:ageString "31"@es .
print() del código anterior print() comentando las órdenes bind()
Recorrer grafo
• Todas las tripletas de un grafo:
• Tripletas de un grafo con algún elemento conocido: g.triples()
• triples() devuelve un generador, no una lista.
• Muy útil para evitar consultas SPARQL sencillas.
• El parámetro de triples() es una 3-tupla: sujeto, predicado, objeto.
• En la tupla se le da valor a las posiciones conocidas con objetos de modelo.
• Las posiciones desconocidas se dejan a None.
for a_triple in g:
pass # Do stuff with your triples
for a_triple in g.triples( (None, RDF.type, None) ): # Just triples with rdf:type as predicate
pass # Do stuff with your triples
Recorrer grafo
• Slicing de Python: sintaxis alternativa a g.triples ( (s,p,o) ):
• g[example.Bob] ↔ g.triples( (example.Bob, None, None) )
• En general, g[x] ↔ tripletas en que x es sujeto
• g[example.Bob : foaf.age] ↔ g.triples((example.Bob, foaf.age , None))
• En general, g[x:y] ↔ tripletas en que x es sujeto e y predicado.
• g[: foaf.age: Literal(31)] ↔ g.triples((None, foaf.age, Literal(31)) )
• En general, g[x:y:z] ↔ tripletas en que x es sujeto, y predicado y z objeto.
• x, y y z pueden ser vacíos. Equivaldría a usar None en la posición correspondiente de
g.triples( (s,p,o) )
Consultar grafo
• Rdflib es compatible con SPARQL.
• Cada ResultRow contiene una tupla ordenada de resultados. El
orden lo marca la consulta SELECT.
• Los resultados también se pueden recorrer usando nombres de variables
query_result = g.query(
""" SELECT ?s ?p WHERE {
?s a ?p
} """)
for a_row in query_result:
print(a_row, type(a_row)) # object ResultRow, it contains sorted model objects
for a_row in query_result:
# Equivalent ways to access the results using variable names
print(a_row.s)
print(a_row["s"])
Moralejas
En general rdflib es una librería válida. Casi todas las
alternativas en Python para tratamiento de RDF se
construyen sobre rdflib. Pero tras usarla durante 7 años…
He visto cosas soldado…
¡Y qué cosas!
¡No las soportarías!
Moralejas: ¿<> en URIs?
• Al mezclar rdflib con otras módulos para análisis de RDF pueden
aparecer contradicciones debido a la presencia o ausencia de
caracteres “<“ y “>”.
• En las serializaciones de RDF, las URIs se rodean de <>.
• En cambio, en rdflib, al instanciar una URIRef no debe haber <>.
• De la misma forma, no esperes caracteres <> al obtener el valor de una URI
labra = URIRef("http://example.org/Labra") # That's OK
print(labra) # http://example.org/Labra
labra = URIRef("<http://example.org/Labra>") # It will crash here
Moralejas: soporte a contenido dudoso
• Ejemplo: enconding de caracteres no ASCII:
• En teoría, una URI tiene un conjunto de caracteres válidos limitados.
• Caracteres especiales como ‘ñ’ deberían ser utilizados usando algún
codificación.
g = Graph()
g.add( (URIRef("http://example.org/España"), RDF.type, example.Country) )
print(g.serialize(format="turtle").decode("utf-8"))
g = Graph()
g.add( (URIRef("http://example.org/España"), RDF.type, example.Country) )
print(g.serialize(format="nt").decode("utf-8"))
Moralejas: encoding
• Error frecuente: al parsear/serializar, rdflib rompe con errores
confusos que hablan de códecs.
• Habitual cuando tratas con grafos que contienen labels en idiomas con
caracteres no ASCII.
• A veces ocurre que parsea datos, pero no los serializa después.
• Ante esto, parsear y serializar especificando encoding (habitualmente utf-8)
g.serialize(destination="example_out.nt",
format="nt",
encoding="utf-8")
g.parse("example.ttl",
format="turtle",
encoding="utf-8")
Moralejas: grandes cargas de datos
• Contras: gran consumo de RAM, parseo muy lento.
• Ejemplos de consumo (un hilo, Intel core i7):
• 0,5 M tripletas  32 segundos, 0,62 GB
• 1 M tripletas  1 minuto 11 segundos, 1,26 GB
• 7,7 M tripletas  8 minutos 26 segundos, 6.1 GB
• Ejemplos de grandes datasets*:
• Wikidata: 1.200 M statements (más tripletas debido a qualifiers).
• Capítulo inglés de DBpedia: 580 M.
• DBpedia: 3.000 M.
• … Rdflib no alcanza para hacer procesamiento en fuentes de esta
dimensión.
*Números aproximados a fecha de 03/03/2021
Rdflib
From ZERO to HERO in an hour
Daniel Fernández Álvarez
fernandezalvdaniel@uniovi.es
I got it… I think

Más contenido relacionado

PPTX
Python dictionary
PDF
Python-03| Data types
PPTX
Operators in java
PPTX
PDF
C++ Standard Template Library
PPTX
Jump statment in python
PDF
How to use Map() Filter() and Reduce() functions in Python | Edureka
PPTX
Stack using Linked List
Python dictionary
Python-03| Data types
Operators in java
C++ Standard Template Library
Jump statment in python
How to use Map() Filter() and Reduce() functions in Python | Edureka
Stack using Linked List

La actualidad más candente (20)

PDF
Python programming : Files
PPT
JavaScript Object Notation (JSON)
PDF
Character Array and String
PDF
Applicative Functor
PDF
Hot C++: Rvalue References And Move Semantics
PPT
Data structures using C
PDF
Exception handling in plsql
PPT
PHP Security
PPT
Data structures
PPTX
Java Generics
PDF
MySQL developing Store Procedure
PPTX
Fundamental of C Programming (Data Types)
PPT
File handling in C++
PPTX
Classes objects in java
PPTX
Concept of c data types
PDF
Strings in Python
PDF
Introduction to Python
PPTX
PPT
CPU INPUT OUTPUT
PPTX
ShEx by Example
Python programming : Files
JavaScript Object Notation (JSON)
Character Array and String
Applicative Functor
Hot C++: Rvalue References And Move Semantics
Data structures using C
Exception handling in plsql
PHP Security
Data structures
Java Generics
MySQL developing Store Procedure
Fundamental of C Programming (Data Types)
File handling in C++
Classes objects in java
Concept of c data types
Strings in Python
Introduction to Python
CPU INPUT OUTPUT
ShEx by Example
Publicidad

Similar a Mini tutorial rdflib (20)

PDF
Ontologia1
PPT
Por qué Ruby
PDF
Linked data con R
PDF
Lenguaje de programación Ruby
PDF
Scala en proyectos de vinculación Ancap-UR - 2013-03
PDF
Curso de Python
PPT
Presentacion swoogle
PPTX
16 Alternativas XML
PDF
Análisis de datos con Apache Spark
PPTX
Codemotion 2016 - d3.js un taller divertido y difícil
PPTX
KEY
Web semántica y linked data la web como bd
PPTX
Tripletas De Sistemas Basados En El Conocimiento
PPTX
Tripletas De Sistemas Basados En El Conocimiento
PPTX
Tripletas De Sistemas Basados En El Conocimiento
PPTX
Tripletas De Sistemas Basados En El Conocimiento
PDF
Tutorial en Apache Spark - Clasificando tweets en realtime
PPT
PPT
PDF
Jorge lopez web_apps
Ontologia1
Por qué Ruby
Linked data con R
Lenguaje de programación Ruby
Scala en proyectos de vinculación Ancap-UR - 2013-03
Curso de Python
Presentacion swoogle
16 Alternativas XML
Análisis de datos con Apache Spark
Codemotion 2016 - d3.js un taller divertido y difícil
Web semántica y linked data la web como bd
Tripletas De Sistemas Basados En El Conocimiento
Tripletas De Sistemas Basados En El Conocimiento
Tripletas De Sistemas Basados En El Conocimiento
Tripletas De Sistemas Basados En El Conocimiento
Tutorial en Apache Spark - Clasificando tweets en realtime
Jorge lopez web_apps
Publicidad

Más de Daniel Fernández Álvarez (6)

PPTX
Wikidata: qué es y cómo subirse al carro
PDF
Presentation shexer
PPTX
PPTX
Presentation ClassRank WikidataCon 2017
PPTX
Presentation to KILT
PPTX
Slides SEMAPRO 2016 University of Oviedo
Wikidata: qué es y cómo subirse al carro
Presentation shexer
Presentation ClassRank WikidataCon 2017
Presentation to KILT
Slides SEMAPRO 2016 University of Oviedo

Último (20)

PDF
CONFERENCIA-Deep Research en el aula universitaria-UPeU-EduTech360.pdf
PDF
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
PDF
Escuela de Negocios - Robert kiyosaki Ccesa007.pdf
DOCX
Informe_practica pre Final.docxddadssasdddddddddddddddddddddddddddddddddddddddd
PPTX
Doctrina 1 Soteriologuia y sus diferente
PDF
Guia de Tesis y Proyectos de Investigacion FS4 Ccesa007.pdf
PPTX
Presentación de la Cetoacidosis diabetica.pptx
PDF
Didactica de la Investigacion Educativa SUE Ccesa007.pdf
PDF
Romper el Circulo de la Creatividad - Colleen Hoover Ccesa007.pdf
PDF
DI, TEA, TDAH.pdf guía se secuencias didacticas
DOCX
III Ciclo _ Plan Anual 2025.docx PARA ESTUDIANTES DE PRIMARIA
PDF
1. Intrdoduccion y criterios de seleccion de Farm 2024.pdf
PDF
Unidad de Aprendizaje 5 de Matematica 1ro Secundaria Ccesa007.pdf
PDF
IDH_Guatemala_2.pdfnjjjkeioooe ,l dkdldp ekooe
PPTX
caso clínico iam clinica y semiología l3.pptx
PDF
PFB-MANUAL-PRUEBA-FUNCIONES-BASICAS-pdf.pdf
DOCX
V UNIDAD - PRIMER GRADO. del mes de agosto
PDF
ACERTIJO Súper Círculo y la clave contra el Malvado Señor de las Formas. Por ...
PDF
Gasista de unidades unifuncionales - pagina 23 en adelante.pdf
PDF
Cronograma de clases de Práctica Profesional 2 2025 UDE.pdf
CONFERENCIA-Deep Research en el aula universitaria-UPeU-EduTech360.pdf
Unidad de Aprendizaje 5 de Educacion para el Trabajo EPT Ccesa007.pdf
Escuela de Negocios - Robert kiyosaki Ccesa007.pdf
Informe_practica pre Final.docxddadssasdddddddddddddddddddddddddddddddddddddddd
Doctrina 1 Soteriologuia y sus diferente
Guia de Tesis y Proyectos de Investigacion FS4 Ccesa007.pdf
Presentación de la Cetoacidosis diabetica.pptx
Didactica de la Investigacion Educativa SUE Ccesa007.pdf
Romper el Circulo de la Creatividad - Colleen Hoover Ccesa007.pdf
DI, TEA, TDAH.pdf guía se secuencias didacticas
III Ciclo _ Plan Anual 2025.docx PARA ESTUDIANTES DE PRIMARIA
1. Intrdoduccion y criterios de seleccion de Farm 2024.pdf
Unidad de Aprendizaje 5 de Matematica 1ro Secundaria Ccesa007.pdf
IDH_Guatemala_2.pdfnjjjkeioooe ,l dkdldp ekooe
caso clínico iam clinica y semiología l3.pptx
PFB-MANUAL-PRUEBA-FUNCIONES-BASICAS-pdf.pdf
V UNIDAD - PRIMER GRADO. del mes de agosto
ACERTIJO Súper Círculo y la clave contra el Malvado Señor de las Formas. Por ...
Gasista de unidades unifuncionales - pagina 23 en adelante.pdf
Cronograma de clases de Práctica Profesional 2 2025 UDE.pdf

Mini tutorial rdflib

  • 1. Rdflib From ZERO to HERO in an hour Daniel Fernández Álvarez fernandezalvdaniel@uniovi.es I got it… I think
  • 2. Rdflib es… • Librería para manejo de RDF: • Parseo y serialización • Múltiples formatos: N-triples, turtle, rdf/XML, JSON-LD (con plug-in)… • Modelo de grafo en memoria: • Creación • Modificación • Consulta (interfaz SPARQL) • Soporte a quads (named graphs). • Lenguajes de programación: • Python • Posible utilizarlo en R
  • 3. Rdflib no es … • …un triplestore*: • Verdaderos triplestores: Virtuoso, BlazeGraph, Neptune… • … apta para BigData*: • Contenido del grafo cargado en memoria. • … una librería para lanzar consultas contra endpoints: • sparqlwrapper, de los los mismos desarrolladores, sí sirve para ello. * Puede ser utilizada junto con algunas bases de datos (ej: Berkeley DB) para hacer su contenido persistente… … pero si necesitas eso, usa un triplestore ;)
  • 4. Parsear un grafo Local, remoto, string from rdflib import Graph # Local graph g = Graph() g.parse("example.ttl", # param 'source' format="turtle") # Remote graph g = Graph() g.parse("https://raw.githubusercontent.com/DaniFdezAlvarez/" "shexerp3/develop/test/t_files/t_graph_1.ttl", format="turtle") # Graph in a 'str' object dumb_g_str = "<http://ex.org/Asturias> <http://ex.org/capital> <http://ex.org/Oviedo> ." g = Graph() g.parse(data=dumb_g_str, format="nt") • Parámetro source: • Fichero local o remoto • Parámetro data: • str • Parámetro format: • Fundamental (rdflib no adivina sintaxis) • Rdf/xml por defecto.
  • 5. Parsear un grafo Local, string • Parámetro destination: • Fichero local • Por defecto, None • Si destination es None, retorna objeto ‘bytes’ • Convertir ‘bytes’ a ‘str’ con decode() • Parámetro format: • Rdf/xml por defecto. • No adivina formato por la extensión especificada. g = Graph() g.parse("example.ttl", format="turtle") g.serialize(destination="example_out.nt", # To local file format="nt") str_g = g.serialize(format="nt") # If 'destination' is None # (deftault value), the content # is returned as a bytes object print(str_g) print(type(str_g)) # type(str_g) --> 'bytes' str_g = str_g.decode("utf-8") print(str_g) # type(str_g) --> 'str' print(type(str_g))
  • 6. Modificar/crear grafo • Cada tripleta es una 3-tupla de Python. • Tuplas: conjuntos ordenados e inmutables. • Las tripletas se componen de objetos de modelo de rdflib: • URI  rdflib.URIRef • Literal  rdflib.Literal • Nodo anónimo  rdflib.BNode • Añadir una tripleta a un grafo g: • g.add( a_triple ) # type(a_triple) == ‘tuple’
  • 7. Modelo Rdflib: URIs • URIRef • Representa cualquier entidad con una URI (clases, instancias, propiedades). • Instancias de URIRef usando constructor: • Instancias de URIRef usando rdflib.Namespace: • Rdflib incluye algunos namespaces preconstruidos: RDF, RDFS, OWL, XSD. • Aconsejable: hacer binding del namespace. • Asocia un prefijo reconocible a cierto namespace al serializar. URIRef("http://example.org/Labra") example = Namespace("http://example.org/") labra = example.Labra example = Namespace("http://example.org/") g.bind("ex", example)
  • 8. Modelo Rdflib: literales • Literal: • Representa cualquier tipo de literal. • Instancias con constructor. • Parámetros: • value: valor del literal. • datatype (opcional): tipo de dato, especificado en forma de URI (URIRef). • lang(opcional): añade una etiqueta de lenguaje al literal (en, es…). • Especificación de datatype: • Si no se rellena datatype, rdflib es capaz de mapear el type() de value con los elementos más comunes de XSD. • CONSEJO: su mapeo puede no ser perfecto. Si se puede conocer el tipo a priori, usar un datatype explícito.
  • 9. Modelo Rdflib: nodos anónimos • BNode: • Representa nodos anónimos (Blank Nodes). • Instancias con constructor: • En general, sin parámetros. Puedes especificar un id para tu BNode con el parámetro value si el contexto lo requiere. • Cuando operes con un nodo anónimo, recuerda guardar un puntero al objeto BNode instanciado para poder referenciarlo desde diferentes tripletas. apple_anonymous = BNode() g.add((example.Labra, example.holds, apple_anonymous)) g.add((apple_anonymous, RDF.type, example.Apple)) g.add((apple_anonymous, example.color, example.Green))
  • 10. Modelo Rdflib: tripletas from rdflib import Graph, URIRef, Literal, BNode, Namespace, RDF, XSD g = Graph() example = Namespace("http://example.org/") g.bind("ex", example) foaf = Namespace("http://xmlns.com/foaf/0.1/") g.bind("foaf", foaf) a_triple = (example.Labra, RDF.type, foaf.Person) g.add(a_triple) g.add( (URIRef("http://example.org/Labra"), foaf.ageString, Literal("31", lang="es") ) ) g.add( (example.Labra, foaf.age, Literal(31) ) ) g.add( (example.Labra, foaf.ageFloat, Literal("31", datatype=XSD.float) ) ) apple_anonymous = BNode() g.add((example.Labra, example.holds, apple_anonymous)) g.add((apple_anonymous, RDF.type, example.Apple)) g.add((apple_anonymous, example.color, example.Green)) g.add((apple_anonymous, example.isTasty, Literal(True))) print(g.serialize(format="turtle").decode("utf-8"))
  • 11. Efecto de bind @prefix ex: <http://example.org/> . @prefix foaf: <http://xmlns.com/foaf/0.1/> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix xml: <http://www.w3.org/XML/1998/namespace> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . ex:Labra a foaf:Person ; ex:holds [ a ex:Apple ; ex:color ex:Green ; ex:isTasty true ] ; foaf:age 31 ; foaf:ageFloat "31.0"^^xsd:float ; foaf:ageString "31"@es . @prefix ns1: <http://example.org/> . @prefix ns2: <http://xmlns.com/foaf/0.1/> . @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> . @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . @prefix xml: <http://www.w3.org/XML/1998/namespace> . @prefix xsd: <http://www.w3.org/2001/XMLSchema#> . ns1:Labra a ns2:Person ; ns1:holds [ a ns1:Apple ; ns1:color ns1:Green ; ns1:isTasty true ] ; ns2:age 31 ; ns2:ageFloat "31.0"^^xsd:float ; ns2:ageString "31"@es . print() del código anterior print() comentando las órdenes bind()
  • 12. Recorrer grafo • Todas las tripletas de un grafo: • Tripletas de un grafo con algún elemento conocido: g.triples() • triples() devuelve un generador, no una lista. • Muy útil para evitar consultas SPARQL sencillas. • El parámetro de triples() es una 3-tupla: sujeto, predicado, objeto. • En la tupla se le da valor a las posiciones conocidas con objetos de modelo. • Las posiciones desconocidas se dejan a None. for a_triple in g: pass # Do stuff with your triples for a_triple in g.triples( (None, RDF.type, None) ): # Just triples with rdf:type as predicate pass # Do stuff with your triples
  • 13. Recorrer grafo • Slicing de Python: sintaxis alternativa a g.triples ( (s,p,o) ): • g[example.Bob] ↔ g.triples( (example.Bob, None, None) ) • En general, g[x] ↔ tripletas en que x es sujeto • g[example.Bob : foaf.age] ↔ g.triples((example.Bob, foaf.age , None)) • En general, g[x:y] ↔ tripletas en que x es sujeto e y predicado. • g[: foaf.age: Literal(31)] ↔ g.triples((None, foaf.age, Literal(31)) ) • En general, g[x:y:z] ↔ tripletas en que x es sujeto, y predicado y z objeto. • x, y y z pueden ser vacíos. Equivaldría a usar None en la posición correspondiente de g.triples( (s,p,o) )
  • 14. Consultar grafo • Rdflib es compatible con SPARQL. • Cada ResultRow contiene una tupla ordenada de resultados. El orden lo marca la consulta SELECT. • Los resultados también se pueden recorrer usando nombres de variables query_result = g.query( """ SELECT ?s ?p WHERE { ?s a ?p } """) for a_row in query_result: print(a_row, type(a_row)) # object ResultRow, it contains sorted model objects for a_row in query_result: # Equivalent ways to access the results using variable names print(a_row.s) print(a_row["s"])
  • 15. Moralejas En general rdflib es una librería válida. Casi todas las alternativas en Python para tratamiento de RDF se construyen sobre rdflib. Pero tras usarla durante 7 años… He visto cosas soldado… ¡Y qué cosas! ¡No las soportarías!
  • 16. Moralejas: ¿<> en URIs? • Al mezclar rdflib con otras módulos para análisis de RDF pueden aparecer contradicciones debido a la presencia o ausencia de caracteres “<“ y “>”. • En las serializaciones de RDF, las URIs se rodean de <>. • En cambio, en rdflib, al instanciar una URIRef no debe haber <>. • De la misma forma, no esperes caracteres <> al obtener el valor de una URI labra = URIRef("http://example.org/Labra") # That's OK print(labra) # http://example.org/Labra labra = URIRef("<http://example.org/Labra>") # It will crash here
  • 17. Moralejas: soporte a contenido dudoso • Ejemplo: enconding de caracteres no ASCII: • En teoría, una URI tiene un conjunto de caracteres válidos limitados. • Caracteres especiales como ‘ñ’ deberían ser utilizados usando algún codificación. g = Graph() g.add( (URIRef("http://example.org/España"), RDF.type, example.Country) ) print(g.serialize(format="turtle").decode("utf-8")) g = Graph() g.add( (URIRef("http://example.org/España"), RDF.type, example.Country) ) print(g.serialize(format="nt").decode("utf-8"))
  • 18. Moralejas: encoding • Error frecuente: al parsear/serializar, rdflib rompe con errores confusos que hablan de códecs. • Habitual cuando tratas con grafos que contienen labels en idiomas con caracteres no ASCII. • A veces ocurre que parsea datos, pero no los serializa después. • Ante esto, parsear y serializar especificando encoding (habitualmente utf-8) g.serialize(destination="example_out.nt", format="nt", encoding="utf-8") g.parse("example.ttl", format="turtle", encoding="utf-8")
  • 19. Moralejas: grandes cargas de datos • Contras: gran consumo de RAM, parseo muy lento. • Ejemplos de consumo (un hilo, Intel core i7): • 0,5 M tripletas  32 segundos, 0,62 GB • 1 M tripletas  1 minuto 11 segundos, 1,26 GB • 7,7 M tripletas  8 minutos 26 segundos, 6.1 GB • Ejemplos de grandes datasets*: • Wikidata: 1.200 M statements (más tripletas debido a qualifiers). • Capítulo inglés de DBpedia: 580 M. • DBpedia: 3.000 M. • … Rdflib no alcanza para hacer procesamiento en fuentes de esta dimensión. *Números aproximados a fecha de 03/03/2021
  • 20. Rdflib From ZERO to HERO in an hour Daniel Fernández Álvarez fernandezalvdaniel@uniovi.es I got it… I think