After two and half months of intense collaborative development, we (@kristoffer.carlsson, @pfitzseb, and myself, based on original work by @Keno) are pleased to announce a fully-featured debugging stack for Julia. You can read details in a new blog post:
How does one run @interpret MyPackageTests
for a package that follows the usual separation of src
and test
directories?
Currently it’s a bit more involved than @interpret
, unfortunately. Check out the test/utils.jl
file and try something like
run_test_by_eval("name of tests", filename, 10^6)
where filename
is the absolute path to your test file. 10^6 controls the maximum number of statements the interpreter will run before giving up and switching to compiled code.
Congratulations and great work by all involved!
This has been epic to watch come together,
and the side-effects bring wide ranging improvements to the ecosystem.
(E.g. Revise.jl v2.0)
Awesome stuff. But how do you set a break point?
Am I doing something wrong with JuliaInterpreter
, or is broadcasting just not implemented yet?
In [14]: x = rand(1:500, 16000);
In [15]: @interpret x .* x
UndefVarError: .* not defined
Stacktrace:
[1] top-level scope at /home/adam/.julia/packages/JuliaInterpreter/62ZyY/src/construct.jl:638
[2] execute_request(::ZMQ.Socket, ::IJulia.Msg) at /home/adam/.julia/packages/IJulia/4UizY/src/execute_request.jl:67
[3] #invokelatest#1 at ./essentials.jl:742 [inlined]
[4] invokelatest at ./essentials.jl:741 [inlined]
[5] eventloop(::ZMQ.Socket) at /home/adam/.julia/packages/IJulia/4UizY/src/eventloop.jl:8
[6] (::getfield(IJulia, Symbol("##15#18")))() at ./task.jl:259
In any case, all of this is very exciting. Kudos to everyone involved.
Nicely done all.
That’s just a case of Julia itself behaving poorly — and same problem as @which x .* x
. Instead try @interpret broadcast(*, x, x)
or f(x) = x .* x; @interpret f(x)
.
Ah. Makes sense. I still haven’t entirely wrapped my head around how arguments to macros work. Thanks!
All three packages support the methods in JuliaInterpreter, which is what’s documented in Debugger’s README as linked by Stefan. Moreover,
- in Juno you can just click in the leftmost column (you have to have fully-updated atom packages
ink
andjulia-client
) - in Rebugger you can just hit
b
orc
when you come to a line that you want to set a breakpoint at
Very Nice! Thanks a lot for this.
How well does this handle things as @async while true .... end
things? Last time I checked it didn’t really. (mainly interested in breakpoint on error stuff)
- This is awesome, thanks to all involved!!
- You might want to change the README’s Usage section to mention that one has to use
Juno.@enter
when running in Juno (this confused me until I read the blog post).
It can’t work through tasks, at least not yet. Works fine without the @async
, though. In Rebugger:
julia> using Rebugger
julia> function foo()
while true
error("oops")
end
end
foo (generic function with 1 method)
julia> foo()
ERROR: oops
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] foo() at ./REPL[2]:3
[3] top-level scope at none:0
interpret> foo() # here I hit Meta-i followed by Enter (to run until breakpoint)
foo() in Main at REPL[2]:2
foo() in Main at REPL[2]:2
error(s::AbstractString) in Base at error.jl:33
s = oops
33 error(s::AbstractString) = begin
33 throw(ErrorException(s))
end
Ok cool, Yea the main issues with debugging I’ve had recently were related to some rendering package I’m working on that let’s you asyncronous interact with what’s displayed. But I’ll somehow find a way to use these tools with it during development! Thanks again
How to remove breakpoints when using Debugger.jl? It doesn’t seem to reexport remove()
or disable()
from JuliaInterpreter.
Hi, confess that have been having some difficulties using the debugger (btw, thanks a LOT for this work). Shouldn’t the MethodError
be caught (at least this one isn’t)?
julia> using Debugger, JuliaInterpreter
julia> cd("c:/v");using GMT, Webview
julia> break_on(:error)
julia> grdcontour("@osu91a1f_16.nc", R=:d, J=:H14, cont=10, A="50+f7p", G=(params=(dist="4i",),), L=(-1000,-1), W=((contour=1,pen="thinnest,-"), (annot=1, pen="thin,-")), T=(gap=("0.1i","0.02i"),), Vd=1)
ERROR: MethodError: no method matching *(::String, ::Tuple{String,String})
Closest candidates are:
*(::Any, ::Any, ::Any, ::Any...) at operators.jl:502
*(::Union{AbstractChar, AbstractString}, ::Union{AbstractChar, AbstractString}...) at strings/basic.jl:229
*(::AbstractString, ::Missing) at missing.jl:144
Stacktrace:
[1] add_opt(::NamedTuple{(:params,),Tuple{NamedTuple{(:dist,),Tuple{String}}}}, ::NamedTuple{(:params,),Tuple{Tuple{String,typeof(GMT.helper_decorated)}}}, ::Nothing) at C:\j\.julia\v0.7\GMT\src\common_options.jl:913
[2] add_opt(::String, ::Char, ::Dict{Symbol,Any}, ::Array{Symbol,2}, ::NamedTuple{(:params,),Tuple{Tuple{String,typeof(GMT.helper_decorated)}}}, ::Bool, ::Nothing) at C:\j\.julia\v0.7\GMT\src\common_options.jl:869
[3] add_opt at C:\j\.julia\v0.7\GMT\src\common_options.jl:867 [inlined]
[4] #grdcontour#80(::Bool, ::Base.Iterators.Pairs{Symbol,Any,NTuple{9,Symbol},NamedTuple{(:R, :J, :cont, :A, :G, :L, :W, :T, :Vd),Tuple{Symbol,Symbol,Int64,String,NamedTuple{(:params,),Tuple{NamedTuple{(:dist,),Tuple{String}}}},Tuple{Int64,Int64},Tuple{NamedTuple{(:contour, :pen),Tuple{Int64,String}},NamedTuple{(:annot, :pen),Tuple{Int64,String}}},NamedTuple{(:gap,),Tuple{Tuple{String,String}}},Int64}}}, ::Function, ::String, ::Array{Any,1}) at C:\j\.julia\v0.7\GMT\src\grdcontour.jl:95
[5] #grdcontour at .\none:0 [inlined] (repeats 2 times)
[6] top-level scope at none:0
We should reexport them as well. You can use Debugger.JuliaInterpreter.remove
for now.
You need to actually run the debugger (with @enter
). Otherwise you are just executing normal julia.
Ghrrr, sure. I did it yesterday but today I must be convinced that I already know how to use it (which I obviously don’t. Have also issues breaking at deep nested methods but that’s probably for another question).