Why is there an inconsistent behaviour in PyCall while adding a directory to the path?

I’m trying to add the current directory to sys.path. The step works if I set index using a string, but fails for the recommended dot overload, or if I use a symbol to access the path.

julia> using PyCall

julia> s=pyimport("sys")
PyObject <module 'sys' (built-in)>

julia> s.path
4-element Array{String,1}:
 "/project/jb6888/anaconda3/lib/python37.zip"           
 "/project/jb6888/anaconda3/lib/python3.7"              
 "/project/jb6888/anaconda3/lib/python3.7/lib-dynload"  
 "/project/jb6888/anaconda3/lib/python3.7/site-packages"

julia> pushfirst!(PyVector(s.path),pwd())
PyObject ['/home/jb6888', '/project/jb6888/anaconda3/lib/python37.zip', '/project/jb6888/anaconda3/lib/python3.7', '/project/jb6888/anaconda3/lib/python3.7/lib-dynload', '/project/jb6888/anaconda3/lib/python3.7/site-packages']

julia> s.path
4-element Array{String,1}:
 "/project/jb6888/anaconda3/lib/python37.zip"           
 "/project/jb6888/anaconda3/lib/python3.7"              
 "/project/jb6888/anaconda3/lib/python3.7/lib-dynload"  
 "/project/jb6888/anaconda3/lib/python3.7/site-packages"

The sys.path is unchanged this way. Using a symbol doesn’t work as well

julia> pushfirst!(PyVector(s[:path]),pwd())
┌ Warning: `getindex(o::PyObject, s::Symbol)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o.s` instead of `o[:s]`.
│   caller = top-level scope at none:0
└ @ Core none:0
PyObject ['/home/jb6888', '/project/jb6888/anaconda3/lib/python37.zip', '/project/jb6888/anaconda3/lib/python3.7', '/project/jb6888/anaconda3/lib/python3.7/lib-dynload', '/project/jb6888/anaconda3/lib/python3.7/site-packages']

julia> s.path
4-element Array{String,1}:
 "/project/jb6888/anaconda3/lib/python37.zip"           
 "/project/jb6888/anaconda3/lib/python3.7"              
 "/project/jb6888/anaconda3/lib/python3.7/lib-dynload"  
 "/project/jb6888/anaconda3/lib/python3.7/site-packages"

but using a string works even though the method is deprecated

julia> pushfirst!(PyVector(s["path"]),pwd())
┌ Warning: `getindex(o::PyObject, s::AbstractString)` is deprecated in favor of dot overloading (`getproperty`) so elements should now be accessed as e.g. `o."s"` instead of `o["s"]`.
│   caller = top-level scope at none:0
└ @ Core none:0
PyObject ['/home/jb6888', '/project/jb6888/anaconda3/lib/python37.zip', '/project/jb6888/anaconda3/lib/python3.7', '/project/jb6888/anaconda3/lib/python3.7/lib-dynload', '/project/jb6888/anaconda3/lib/python3.7/site-packages']

julia> s.path
5-element Array{String,1}:
 "/home/jb6888"                                         
 "/project/jb6888/anaconda3/lib/python37.zip"           
 "/project/jb6888/anaconda3/lib/python3.7"              
 "/project/jb6888/anaconda3/lib/python3.7/lib-dynload"  
 "/project/jb6888/anaconda3/lib/python3.7/site-packages"

I’m using PyCall v1.91.2, which seems to be the recent version

It seems I hadn’t read the docs (or even the deprecation message) carefully, and it should be

pushfirst!(PyVector(s."path"),pwd())

with path as a string. The behavior is different otherwise

julia> s.path
5-element Array{String,1}:
 "/home/jb6888"                                         
 "/project/jb6888/anaconda3/lib/python37.zip"           
 "/project/jb6888/anaconda3/lib/python3.7"              
 "/project/jb6888/anaconda3/lib/python3.7/lib-dynload"  
 "/project/jb6888/anaconda3/lib/python3.7/site-packages"

julia> s."path"
PyObject ['/home/jb6888', '/project/jb6888/anaconda3/lib/python37.zip', '/project/jb6888/anaconda3/lib/python3.7', '/project/jb6888/anaconda3/lib/python3.7/lib-dynload', '/project/jb6888/anaconda3/lib/python3.7/site-packages']

Using the string returns a PyObject which is then extended. Without a string it returns an array which is not linked to the PyObject anymore.

1 Like