Hi,
I’m trying to use PyCall to call the hnswlib python bindings from julia. The following MWE with a module defined at the repl works as expected. And also a slightly expanded version of that module where the find_ann
function actually does non-trivial work with hnswlib also works.
julia> module A
using PyCall
hnswlib = pyimport("hnswlib")
function find_ann(X::AbstractArray{T,2};
metric = "l2") where T<:Real
n_elements,ndims = size(X)
# Declaring index
p = hnswlib.Index(space=metric, dim=ndims) # possible options are l2, cosine or ip
end
end
Main.A
julia> using .A
julia> X = randn(100,10);
julia> A.find_ann(X)
PyObject <HNSW-lib index>
So then I start to develop a small package that I want the find_ann
function to be a part of. I’m getting an error I don’t understand when I try to define my find_ann
function inside the package. Right now my package consists of three files, MyPackage.jl, nn.jl, and Utils.jl. Utils.jl currently just has one simple function that only calls stuff from base julia. MyPackage.jl is:
module MyPackage
using LinearAlgebra, SparseArrays, Statistics
using PyCall
include("Utils.jl")
include("nn.jl")
end
And then nn.jl is:
export find_ann
hnswlib = pyimport("hnswlib")
function find_ann(X::AbstractArray{T,2};
metric = "l2") where T<:Real
n_elements,ndims = size(X)
# Declaring index
p = hnswlib.Index(space=metric, dim=ndims) # possible options are l2, cosine or ip
end
This goes into the standard package folder structure:
- MyPackage/
-Project.toml
-src/
-MyPackage.jl
-nn.jl
-Utils.jl
And I do ] dev /path/to/MyPackage/
to add the package to my julia environment.
The problem is that find_ann
doesn’t work when it’s defined inside MyPackage
, even though, as you can see, it’s literally been copy-pasted from the module I defined in the repl. When I try it I get:
julia> using MyPackage
[ Info: Precompiling MyPackage [UUID-omitted for Discourse]
julia> X = randn(100,10);
julia> find_ann(X)
ERROR: ArgumentError: ref of NULL PyObject
Stacktrace:
[1] getproperty(::PyCall.PyObject, ::String) at /home/patrick/.julia/packages/PyCall/zqDXB/src/PyCall.jl:296
[2] getproperty(::PyCall.PyObject, ::Symbol) at /home/patrick/.julia/packages/PyCall/zqDXB/src/PyCall.jl:306
[3] find_ann(::Array{Float64,2}; metric::String) at /home/patrick/julia-dev/SSLClustering/src/nn.jl:10
[4] find_ann(::Array{Float64,2}) at /home/patrick/julia-dev/SSLClustering/src/nn.jl:7
[5] top-level scope at REPL[4]:1
julia>
Does anyone know why I get that ref of NULL PyObject
error only when find_ann
is defined in MyPackage
and not in the repl defined module? Thanks!
P.S. This is on linux, julia 1.4.1, PyCall v1.91.4.