# Converting Julia arrays, views to NumPy arrays via PyCall

**URL:** <https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186>\
**Category:** General Usage\
**Tags:** pycall, pythoncall\
**Created:** [May 15, 2021, 4:08am UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186 "2021-05-15T04:08:40Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![SCKnight](https://avatars.discourse-cdn.com/v4/letter/s/e68b1a/32.png) [@SCKnight](https://discourse.julialang.org/u/SCKnight)\
**Post date:** [May 15, 2021, 4:08am UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/1 "2021-05-15T04:08:40Z")

</div>

I am trying to make some Julia code work with Python, and I am having some trouble understanding why certain kind of Julia arrays are able to translate to NumPy arrays. A regular Julia `Array` seems to get translated just fine, but if I try to use `@view` or `reinterpret` I get a Python `list` rather than a `numpy.ndarray`.

Am I doing something wrong?

```julia
julia> A = rand(Int,256);

julia> pyA = PyObject(A);

julia> pytypeof(pyA)
PyObject <class 'numpy.ndarray'>

julia> pyA_1_to_100 = PyObject(A[1:100]);

julia> pytypeof(pyA_1_to_100)
PyObject <class 'numpy.ndarray'>

julia> pyA_1_to_100_view = PyObject(@view(A[1:100]));

julia> pytypeof(pyA_1_to_100_view)
PyObject <class 'list'>

julia> pyA_reinterpret = PyObject(reinterpret(UInt,A));

julia> pytypeof(pyA_reinterpret)
PyObject <class 'list'>

```

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 16, 2021, 3:10am UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/2 "2021-05-16T03:10:49Z")

</div>

No, you’re not doing anything wrong. Currently PyCall does not support the conversion of `SubArray` or `Base.ReinterpretArray` to NumPy arrays.

```julia
julia> typeof(@view(A[1:100]))
SubArray{Int64,1,Array{Int64,1},Tuple{UnitRange{Int64}},true}

julia> typeof(reinterpret(UInt,A))
Base.ReinterpretArray{UInt64,1,Int64,Array{Int64,1}}

```

I think it is possible to convert more standard Julia array types to NumPy arrays. I’ve created this pull request to try to apply this to types that implement `strides`:  
[https://github.com/JuliaPy/PyCall.jl/pull/876](https://github.com/JuliaPy/PyCall.jl/pull/876)

```julia
julia> applicable(strides, @view(A[1:100]))
true

julia> applicable(strides, reinterpret(UInt,A))
true

```

I’m not sure what the status of the pull request is. Perhaps @stevengj could comment on the state of the PR.

---

<div class="post-metadata">

**Author:** ![SCKnight](https://avatars.discourse-cdn.com/v4/letter/s/e68b1a/32.png) [@SCKnight](https://discourse.julialang.org/u/SCKnight)\
**Post date:** [May 17, 2021, 1:45pm UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/3 "2021-05-17T13:45:00Z")

</div>

Thanks. While we are waiting on the PR to be reviewed or merged, is there any possible workarounds that the user can do? If the PR proves impossible, would it be possible to put these features into a separate package?

---

<div class="post-metadata">

**Author:** ![lungben](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lungben/32/12314_2.png) [@lungben](https://discourse.julialang.org/u/lungben)\
**Post date:** [May 17, 2021, 1:54pm UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/4 "2021-05-17T13:54:32Z")

</div>

The easiest way would be to use standard Julia arrays, but this may be problematic if they are GB-sized or in a very hot loop.  
Or is it possible to move the whole calculation to Julia, removing the need for PyCall?

---

<div class="post-metadata">

**Author:** ![SCKnight](https://avatars.discourse-cdn.com/v4/letter/s/e68b1a/32.png) [@SCKnight](https://discourse.julialang.org/u/SCKnight)\
**Post date:** [May 17, 2021, 2:53pm UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/5 "2021-05-17T14:53:17Z")

</div>

I’m moving large images around, so copying data would be quite problematic. Looking at the PR that @mkitti mentioned, it looks possible to override some of the few PyCall methods to achieve similar functionality.

In particular, if one implemented `NpyArray(a::AbstractArray{T}, revdims::Bool) where T<:PYARR_TYPES` and `pyembed(po::PyObject, jo::Any)` for `SubArray` and `Base.ReinterpretArray` then maybe it will work?

---

<div class="post-metadata">

**Author:** ![cjdoris](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cjdoris/32/213133_2.png) [@cjdoris](https://discourse.julialang.org/u/cjdoris)\
**Post date:** [May 17, 2021, 9:13pm UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/6 "2021-05-17T21:13:48Z")

</div>

You might like to try my package [GitHub - cjdoris/PythonCall.jl: Python and Julia in harmony.](http://github.com/cjdoris/PythonCall.jl), all mutable objects do non-copying conversion to Python and any strided array is usable as a numpy array.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 19, 2021, 2:33am UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/7 "2021-05-19T02:33:46Z")

</div>

> [@cjdoris](#):
>
> You might like to try my package [http://github.com/cjdoris/PythonCall.jl](http://github.com/cjdoris/PythonCall.jl), all mutable objects do non-copying conversion to Python and any strided array is usable as a numpy array.

I may need to consider switching to PythonCall for [Napari.jl](https://github.com/mkitti/Napari.jl) soon for this feature.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [May 19, 2021, 7:08am UTC](https://discourse.julialang.org/t/converting-julia-arrays-views-to-numpy-arrays-via-pycall/61186/8 "2021-05-19T07:08:36Z")

</div>

Ok, here’s the self contained hack:

```julia
julia> using PyCall

julia> A = rand(Int, 256);

julia> pytypeof( PyObject(reinterpret(UInt64, A)) )
PyObject <class 'list'>

julia> pytypeof( PyObject(@view(A[1:100])) )
PyObject <class 'list'>

julia> module PyCallHack
           import PyCall: NpyArray, PYARR_TYPES, @npyinitialize, npy_api, npy_type
           import PyCall: @pycheck, NPY_ARRAY_ALIGNED, NPY_ARRAY_WRITEABLE, pyembed
           import PyCall: PyObject, PyPtr
           const HACKED_ARRAYS = Union{SubArray{T}, Base.ReinterpretArray{T}, Base.ReshapedArray{T}, Base.PermutedDimsArray{T}} where T <: PYARR_TYPES
           function NpyArray(a::HACKED_ARRAYS{T}, revdims::Bool) where T <: PYARR_TYPES
               @npyinitialize
               size_a = revdims ? reverse(size(a)) : size(a)
               strides_a = revdims ? reverse(strides(a)) : strides(a)
               p = @pycheck ccall(npy_api[:PyArray_New], PyPtr,
                   (PyPtr,Cint,Ptr{Int},Cint, Ptr{Int},Ptr{T}, Cint,Cint,PyPtr),
                   npy_api[:PyArray_Type],
                   ndims(a), Int[size_a...], npy_type(T),
                   Int[strides_a...] * sizeof(eltype(a)), a, sizeof(eltype(a)),
                   NPY_ARRAY_ALIGNED | NPY_ARRAY_WRITEABLE,
                   C_NULL)
              return PyObject(p, a)
           end
           pyembed(po::PyObject, jo::HACKED_ARRAYS) = pyembed(po, jo.parent)
       end
Main.PyCallHack

julia> pytypeof( PyObject(reinterpret(UInt64, A)) )
PyObject <class 'numpy.ndarray'>

julia> pytypeof( PyObject(@view(A[1:100])) )
PyObject <class 'numpy.ndarray'>

```
