Pluto.jl icon indicating copy to clipboard operation
Pluto.jl copied to clipboard

Pluto only shows a part of a stacktrace with PythonCall

Open aplavin opened this issue 1 year ago • 4 comments

Pluto's stacktrace doesn't show essential information: image

compared to the Julia REPL:

julia> using PythonCall

julia> pybuiltins.sum(error(i) for i in 1:10)
ERROR: Python: Julia: 1
Stacktrace:
  [1] error(s::Int64)
    @ Base ./error.jl:44
  [2] (::var"#8#9")(i::Int64)
    @ Main ./none:0
  [3] iterate(::Base.Generator{UnitRange{Int64}, var"#8#9"})
    @ Base ./generator.jl:47
  [4] pyjliter_next(self::PythonCall.JlWrap.Iterator)
    @ PythonCall.JlWrap ~/.julia/packages/PythonCall/sQSpa/src/JlWrap/iter.jl:0
  [5] _pyjl_callmethod(f::Any, self_::Ptr{PythonCall.C.PyObject}, args_::Ptr{PythonCall.C.PyObject}, nargs::Int64)
    @ PythonCall.JlWrap ~/.julia/packages/PythonCall/sQSpa/src/JlWrap/base.jl:62
  [6] _pyjl_callmethod(o::Ptr{PythonCall.C.PyObject}, args::Ptr{PythonCall.C.PyObject})
    @ PythonCall.JlWrap.Cjl ~/.julia/packages/PythonCall/sQSpa/src/JlWrap/C.jl:63
  [7] PyObject_CallObject
    @ ~/.julia/packages/PythonCall/sQSpa/src/C/pointers.jl:301 [inlined]
  [8] macro expansion
    @ ~/.julia/packages/PythonCall/sQSpa/src/Core/Py.jl:132 [inlined]
  [9] pycallargs
    @ ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:220 [inlined]
 [10] pycall(f::Py, args::Base.Generator{UnitRange{Int64}, var"#8#9"}; kwargs::@Kwargs{})
    @ PythonCall.Core ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:243
 [11] pycall
    @ ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:233 [inlined]
 [12] (::Py)(args::Base.Generator{UnitRange{Int64}, var"#8#9"})
    @ PythonCall.Core ~/.julia/packages/PythonCall/sQSpa/src/Core/Py.jl:357
 [13] top-level scope
    @ REPL[10]:1
 [14] eval
    @ ./boot.jl:385 [inlined]
 [15] eval_user_input(ast::Any, backend::REPL.REPLBackend, mod::Module)
    @ REPL ~/.julia/juliaup/julia-1.10.4+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:150
 [16] repl_backend_loop(backend::REPL.REPLBackend, get_module::Function)
    @ REPL ~/.julia/juliaup/julia-1.10.4+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:246
 [17] start_repl_backend(backend::REPL.REPLBackend, consumer::Any; get_module::Function)
    @ REPL ~/.julia/juliaup/julia-1.10.4+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:231
 [18] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool, backend::Any)
    @ REPL ~/.julia/juliaup/julia-1.10.4+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:389
 [19] run_repl(repl::REPL.AbstractREPL, consumer::Any)
    @ REPL ~/.julia/juliaup/julia-1.10.4+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:375
 [20] (::Base.var"#1013#1015"{Bool, Bool, Bool})(REPL::Module)
    @ Base ./client.jl:432
 [21] #invokelatest#2
    @ ./essentials.jl:892 [inlined]
 [22] invokelatest
    @ ./essentials.jl:889 [inlined]
 [23] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)
    @ Base ./client.jl:416
 [24] exec_options(opts::Base.JLOptions)
    @ Base ./client.jl:333
 [25] _start()
    @ Base ./client.jl:552
Python stacktrace:
 [1] __next__
   @ ~/.julia/packages/PythonCall/sQSpa/src/JlWrap/iter.jl:39
Stacktrace:
 [1] pythrow()
   @ PythonCall.Core ~/.julia/packages/PythonCall/sQSpa/src/Core/err.jl:92
 [2] errcheck
   @ ~/.julia/packages/PythonCall/sQSpa/src/Core/err.jl:10 [inlined]
 [3] pycallargs
   @ ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:220 [inlined]
 [4] pycall(f::Py, args::Base.Generator{UnitRange{Int64}, var"#8#9"}; kwargs::@Kwargs{})
   @ PythonCall.Core ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:243
 [5] pycall
   @ ~/.julia/packages/PythonCall/sQSpa/src/Core/builtins.jl:233 [inlined]
 [6] (::Py)(args::Base.Generator{UnitRange{Int64}, var"#8#9"})
   @ PythonCall.Core ~/.julia/packages/PythonCall/sQSpa/src/Core/Py.jl:357
 [7] top-level scope
   @ REPL[10]:1

aplavin avatar Aug 04 '24 20:08 aplavin

Thanks @aplavin !

Maybe you could help by figuring out how this works in the REPL? I see 3 stack traces, where are these stored and how are they displayed?

fonsp avatar Aug 05 '24 08:08 fonsp

I think PythonCall just uses the Julia showerror mechanism, see https://github.com/JuliaPy/PythonCall.jl/blob/bcd2bbbf1e75ed88d3814c69730137f551bbdbf2/src/Core/err.jl#L112 and around.

help?> showerror
search: showerror

  showerror(io, e)

  Show a descriptive representation of an exception object e. This method is
  used to display the exception after a call to throw.

aplavin avatar Aug 05 '24 09:08 aplavin

Oof that looks complicated... What do you think is a good solution? Maybe we should not use our fancy stack trace for PyException and just show it terminal-style?

Could you run PlutoRunner.PRETTY_STACKTRACES[] = false in your notebook and see if this is an improvement?

fonsp avatar Aug 06 '24 06:08 fonsp

I won't have capacity to fix this soon, but feel free to make a PR! Search for "integrations" in the PlutoRunner file for doing package speicific thinngs. @schlichtanders maybe you can also help if this is relevant to you?

fonsp avatar Aug 10 '24 19:08 fonsp