JuliaPy / JuliaPy/PythonCall.jl

Segmentation fault when registering Julia-defined Python class with Matplotlib

Abierto
#289 1 comentario 0 reacciones 0 asignados Ver en GitHub
Lenguaje dominante
Julia
Estrellas
1.1k
Forks
86
Merge medio
1 d 22 h
PR fusionados (30 d)
3

Descripción

I have implemented a custom axis transform [according to the documentation](https://matplotlib.org/stable/api/transformations.html):

```julia
SqrtTransform = pytype("SqrtTransform", (matplotlib.transforms.Transform,), [
"__module__" => "__main__",
pyfunc(name="__init__",
function (self)
self.input_dims = 1
self.output_dims = 1
self.is_separable = true
self.has_inverse = true
matplotlib.transforms.Transform.__init__(self)
end),
pyfunc(name="transform_non_affine",
function(self, a)
b = pyconvert(Array, a)
v = similar(b)
sel = b .>= 0
v[sel] .= .√(b[sel])
# v[.!sel] .= NaN
v
end),
pyfunc(name="inverted",
(self) -> SquareTransform())
])

SquareTransform = pytype("SquareTransform", (matplotlib.transforms.Transform,), [
"__module__" => "__main__",
pyfunc(name="__init__",
function (self)
self.input_dims = 1
self.output_dims = 1
self.is_separable = true
self.has_inverse = true
matplotlib.transforms.Transform.__init__(self)
end),
pyfunc(name="transform_non_affine",
function(self, a)
pyconvert(Array, a) .^ 2
end),
pyfunc(name="inverted",
(self) -> SqrtTransform())
])

SqrtScale = pytype("SqrtScale", (matplotlib.scale.ScaleBase,), [
"__module__" => "__main__",
"name" => "sqrt",
pyfunc(name="__init__",
function(self, axis, args...; kwargs...)
matplotlib.scale.ScaleBase.__init__(self, axis)
end),
pyfunc(name="get_transform",
(self) -> SqrtTransform()),
pyfunc(name="set_default_locators_and_formatters",
(self, axis) -> nothing),
pyfunc(name="limit_range_for_scale",
function(self, vmin, vmax, minpos)
max(vmin, 0), max(vmax, 0)
end)])
```

To register this with Matplotlib, one uses
```julia
matplotlib.scale.register_scale(SqrtScale)
```

This works well from a script, but not if I try to put it into a package. If I just put the line registering the transform with Matplotlib after the class definitions, nothing happens, i.e. Matplotlib does not in fact register the new transform. If I instead try to register it from `__init__()`, or from the REPL after having loaded the package, it crashes with the following trace:

```julia
signal (11): Segmentation fault: 11
in expression starting at REPL[4]:1
_PyFunction_Vectorcall at /Users/jagot/work/projects/move-to-pythoncall/.CondaPkg/env/lib/libpython3.11.dylib (unknown line)
PyObject_CallObject at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/cpython/pointers.jl:299 [inlined]
pycallargs at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/abstract/object.jl:210
unknown function (ip: 0x10ce5a8e6)
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
#pycall#59 at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/abstract/object.jl:228
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
do_apply at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
pycall at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/abstract/object.jl:218
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
do_apply at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
#_#11 at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/Py.jl:352
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
do_apply at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
Py at /Users/jagot/.julia/packages/PythonCall/dsECZ/src/Py.jl:352
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
do_call at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
eval_body at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_interpret_toplevel_thunk at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_toplevel_eval_flex at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_toplevel_eval_flex at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_toplevel_eval_flex at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
ijl_toplevel_eval_in at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
eval at ./boot.jl:368 [inlined]
eval_user_input at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:151
repl_backend_loop at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:247
start_repl_backend at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:232
#run_repl#47 at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:369
run_repl at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-5.0/build/default-macmini-x64-5-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:355
jfptr_run_repl_63566.clone_1 at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
#967 at ./client.jl:419
jfptr_YY.967_56999.clone_1 at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_f__call_latest at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
#invokelatest#2 at ./essentials.jl:729 [inlined]
invokelatest at ./essentials.jl:726 [inlined]
run_main_repl at ./client.jl:404
exec_options at ./client.jl:318
_start at ./client.jl:522
jfptr__start_57423.clone_1 at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
true_main at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
jl_repl_entrypoint at /Users/jagot/.julia/juliaup/julia-1.8.5+0.x64.apple.darwin14/lib/julia/libjulia-internal.1.8.dylib (unknown line)
Allocations: 19584391 (Pool: 19573667; Big: 10724); GC: 22
```

Environment:
```julia
Status `~/work/projects/move-to-pythoncall/Project.toml`
[84fb645a] Jagot v0.1.0 `~/.julia/dev/Jagot`
[6099a3de] PythonCall v0.9.12
[274fc56d] PythonPlot v1.0.2
[295af30f] Revise v3.5.2
```

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Línea de trabajo

Reproduce the provided Matplotlib registration example first as a script, then from package initialization and the REPL. Start with PythonCall's pytype and pycall paths shown in the trace, and compare object lifetime and registration behavior across those contexts. Done means package-based registration works without a segmentation fault and the custom scale is registered.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
julia, python
Área
backend, tooling
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Estancado
Claridad
Bastante claro
Aptitud para principiantes
35/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.