JuliaCall: Pass numpy array to julia function as Vector{Float64}

This is a nice example, so I’ll run through the options in detail.

To summarise the problem, you have defined a Julia function myfunc(::Vector{Float64}) and then find that you cannot call it from Python (using JuliaCall) with a list or numpy.ndarray as the argument. This fails because of the default conversion rules when calling a Julia function from Python:

  • list is converted to PyList{Py}
  • numpy.ndarray is converted to PyArray{Float64,1} (in this case)

Option 1 (highly recommended): As suggested in previous replies, make the signature of myfunc more general, e.g. myfunc(::AbstractArray{<:Real}). This is generally a good thing to do in Julia any, but in this case it means that it can be called with a PyArray{Floay64,1} argument, so will work with numpy.ndarray or any other Python array type. However it will still not work with list because PyList{Py} <: AbstractVector{<:Real} is false (because Py <: Real is false).

Option 2: If you can’t do that, then write a Julia wrapper function

myfunc2(a::AbstractVector) = myfunc(convert(Vector{Float64}, a))

and call that instead.

Option 3: If you have done 2 or 3, then you can make it also work with lists by explicitly converting to a numpy array from Python:

jl.myfunc(np.asarray([1.0, 2.0, 3.0]))

Option 4: Or without any changes to myfunc you could instead explicitly convert to a Vector{Float64} from Python:

jl.myfunc(juliacall.convert(jl.Vector[jl.Float64], [1.0, 2.0, 3.0]))

Option 5: Or you can create a wrapper function which does the conversion on the Julia side:

myfunc = jl.seval("pyfunc((a::Py)->myfunc(pyconvert(Vector{Float64}, a)))")

To explain this a bit, pyfunc wraps a Julia function into a Python function, but the arguments are not automatically converted (hence the a::Py argument) and so you can call pyconvert to convert them to the desired type. This option is mostly useful from the Julia side to create a Python callback function.

If I were you I’d do Option 1 and maybe Option 3. Or do Option 4.

4 Likes