Skip to content

Stack trace order is inconsistent #391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
LilithHafner opened this issue Oct 23, 2023 · 2 comments
Open

Stack trace order is inconsistent #391

LilithHafner opened this issue Oct 23, 2023 · 2 comments
Labels
enhancement New feature or request
Milestone

Comments

@LilithHafner
Copy link
Contributor

LilithHafner commented Oct 23, 2023

Is your feature request related to a problem? Please describe.
Python stack traces place the most recent call last, Julia's place the most recent call first. When I the call stack has a bunch of Python function then a bunch of Julia functions, the most recent call is in the middle. I don't like that.

Describe the solution you'd like
It'd be nice if PythonCall printed Python stack traces in julian order and JuliaCall printed julia stack traces in pythonic order.

Julia's Base could also flip the order all stacktraces are printed in :P

@LilithHafner LilithHafner added the enhancement New feature or request label Oct 23, 2023
@cjdoris
Copy link
Collaborator

cjdoris commented Oct 24, 2023

In Julia, PythonCall already has custom stacktrace printing so that the Python stack is in the same order as Julia:

julia> @pyexec """
       global pyinner, pyouter
       def pyinner():
           raise ValueError()
       def pyouter():
           pyinner()
       """

julia> jlinner() = @pyeval "pyouter()"
jlinner (generic function with 1 method)

julia> jlouter() = jlinner()
jlouter (generic function with 1 method)

julia> jlouter()
ERROR: Python: ValueError:
Python stacktrace:
 [1] pyinner
   @ REPL[5]:1:3
 [2] pyouter
   @ REPL[5]:1:5
 [3] <module>
   @ REPL[6]:1:1
Stacktrace:
  [1] pythrow()
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\err.jl:94
  [2] errcheck
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\err.jl:10 [inlined]
  [3] pycallargs(f::Py, args::Py)
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\abstract\object.jl:210
  [4] pycall(::Py, ::Py, ::Vararg{Py}; kwargs::@Kwargs{})
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\abstract\object.jl:228
  [5] pycall
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\abstract\object.jl:218 [inlined]
  [6] Py
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\Py.jl:341 [inlined]
  [7] pyeval(::Type{Py}, code::Py, globals::Module, locals::Tuple{})
    @ PythonCall C:\Users\chris\.julia\dev\PythonCall\src\concrete\code.jl:50
  [8] jlinner
    @ Main .\REPL[6]:1 [inlined]
  [9] jlouter()
    @ Main .\REPL[7]:1
 [10] top-level scope
    @ REPL[8]:1

@cjdoris
Copy link
Collaborator

cjdoris commented Oct 24, 2023

But yes, you're right that from Python, the Julia stack is printed in reverse. This is because custom stack printing has not been implemented on that side, so just uses Base.showerror(io, error, backtrace).

>>> jl.seval("""begin
...     jlinner() = error()
...     jlouter() = jlinner()
... end""")
Julia: jlouter (generic function with 1 method)
>>> def pyinner():
...     jl.seval("jlouter()")
...
>>> def pyouter():
...     pyinner()
...
>>> pyouter()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in pyouter
  File "<stdin>", line 2, in pyinner
  File "C:\Users\chris\.julia\packages\PythonCall\qTEA1\src\jlwrap\module.jl", line 25, in seval
    return self._jl_callmethod($(pyjl_methodnum(pyjlmodule_seval)), expr)
juliacall.JuliaError:
Stacktrace:
 [1] error()
   @ Base .\error.jl:44
 [2] jlinner()
   @ Main .\none:2
 [3] jlouter()
   @ Main .\none:3
 [4] top-level scope
   @ none:1
 [5] eval
   @ .\boot.jl:370 [inlined]
 [6] eval
   @ .\Base.jl:68 [inlined]
 [7] pyjlmodule_seval(self::Module, expr::Py)
   @ PythonCall C:\Users\chris\.julia\packages\PythonCall\qTEA1\src\jlwrap\module.jl:13
 [8] _pyjl_callmethod(f::Any, self_::Ptr{PythonCall.C.PyObject}, args_::Ptr{PythonCall.C.PyObject}, nargs::Int64)
   @ PythonCall C:\Users\chris\.julia\packages\PythonCall\qTEA1\src\jlwrap\base.jl:62
 [9] _pyjl_callmethod(o::Ptr{PythonCall.C.PyObject}, args::Ptr{PythonCall.C.PyObject})
   @ PythonCall.C C:\Users\chris\.julia\packages\PythonCall\qTEA1\src\cpython\jlwrap.jl:47

It would indeed be nice to improve these stack traces.

@cjdoris cjdoris added this to the features milestone Nov 4, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants