JuliaPy / PyCall.jl

Package to call Python functions from the Julia language
MIT License
1.45k stars 186 forks source link

Can't convert from PyPtr to related type #1043

Open hiiroo opened 1 year ago

hiiroo commented 1 year ago

Hello everyone and thanks for the great library. I was trying to use rdflib of Python in PyCall.jl. I'm using macos, Julia 1.9.1 and using ENV["Python"]="" with Conda.jl. With this code,

using PyCall

# Create an empty graph
graph = pyimport("rdflib").Graph()

# Define the namespace
ex = "http://example.org/"

# Define the triples
subject = pyimport("rdflib").URIRef(ex * "subject")
predicate = pyimport("rdflib").URIRef(ex * "predicate")
object = pyimport("rdflib").Literal("object")

# Add the triples to the graph
graph.add((subject, predicate, object))

I got the following output

ERROR: PyError ($(Expr(:escape, :(ccall(#= /Users/hiiroo/.julia/packages/PyCall/ilqDX/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'AssertionError'>
AssertionError('Subject http://example.org/subject must be an rdflib term')
  File "/Users/hiiroo/.julia/conda/3/lib/python3.7/site-packages/rdflib/graph.py", line 532, in add
    assert isinstance(s, Node), "Subject %s must be an rdflib term" % (s,)
hiiroo commented 1 year ago

Additional details;

When the following code run it returns a string "http://example.org/subject1"

s1 = rdflib.URIRef("http://example.org/subject1")

However, when it run in python it returns rdflib.term.URIRef('http://example.org/subject1')

subject = rdflib.URIRef(ex + "subject1")
stevengj commented 1 year ago

You can suppress PyCall's automatic conversion with:

pycall(rdflib.URIRef, PyObject, "http://example.org/subject1")

which tells it to return a raw PyObject rather than trying to convert to a native Julia object (which I guess happens here because rdflib.term.URIRef is a subtype of string).