One-line debugging

Hello,
I’d just like to have a way to easily debug code for terminal-centric people. For instance, right now I have the following situation (which is rather common, though):

  • a test/example script which is added by calling include("script.jl)
  • a function main inside the script which is called by the user
  • a package which is still being tested

In python, I could just use the one-line __import__("ipdb").set_trace() to debug any line in script.jl or in the package.

In Julia, instead, I have to:

  • add using Debugger at the top of the corresponding file
  • add @bp at the line I want to debug
  • add @run at the line where the function is called

Obviously, when I finish debugging (or decide to debug at another point) there’s the risk to leave some unneeded line (while in python I can just remove-copy my line).

So, workflow suggestions are welcome!

Example: a @debug <line-number> macro at the beginning of the function definition which automatically makes it be called with using Debugger, @run and break-point setup or something like that.

Other example: a macro which outputs the output of each instruction in the function (similarly to python’s @snoop).

Doesn’t quite satisfy your requirement of being “terminal-centric”, but I’ve really come to appreciate the debugger in VS code and would highly recommend to at least give it a try.

I already tried VSCode tons of times and despite it’s probably the second best editor in the world, It’s miles away from (neo)vim for me. It’s a shame that Julia decided to support only one editor. Supporting terminal workflows would be much more general and would work in almost any higher-level platform

1 Like

The VSCode debugger is basically just a convenient UI.
You can add breakpoints with Debugger.jl without modifying your source code with e.g. debug> bp add file:line. So yes, you need using Debugger; @enter main(), but that really doesn’t seem too bad to me.
Infiltrator.jl might also be of interest to you.

1 Like

It’s not just @enter main(), it’s @enter a_deeper_function(). It’s very unpractical when you have to debug a function that is a few calls down in the stack.

I know about Infiltrator, and aside from the fact that it still needs using Infiltrator, it’s almost what I need, if we could also step around…

Well, in theory you can just @run main() and the program will stop at the first breakpoint, no? Although you might run into performance issues, I suppose.

I also don’t quite see the issue with needing a using statement, considering you need to do that only once per session?

The problem is that using statements must be inside the module in which the function is defined, otherwise @bp is not recognized… so if I put @bp in the MySeconfdModule, I need to:

  • put using Debugger in MySecondModule
  • executes @enter MyFirstModule.main()
  • press C to toggle compiled mode
  • press c to continue until breakpoint
  • press C again to start debugging

6 steps for debugging, while in Python it’s just a one line (that with snippets becomes a few characters written in the editor). Do that a few times and find the difference :slight_smile:

Well, you can always use Main.@bp in a nested module. But as I said before, if you don’t want to put anything into your file. Just set the breakpoints programatically.

Toggling compiled mode like you’re doing also doesn’t work, because breakpoints won’t work in compiled mode. So it comes down to

  • using Debugger at the top level
  • inserting breakpoints, either via breakpoint(...), in the debug> REPL, or with Main.@bp
  • @run main()
2 Likes

yeah, inserting them programatically is a way indeed. But Main.@bp is the way to go! Does @run start in compiled mode?

No. @run in compiled mode is basically equivalent to running your code without a debugger (except for maybe the toplevel frame).

So there’s no way to automatically turn on compiled mode when using @run?

Why do you want to do that? How do you plan on actually debugging anything, considering that breakpoints don’t work in compiled mode?

Most of the code I develop in my research leads me to computational problems and takes a long time to run in interpreted mode… I usually run a little example to make the code compile first and then run the real instance problem that I want to debug

Yes, sure, but the point of @run is to run until we hit a breakpoint or your program finishes. Automatically switching to compiled mode in @run will therefore always run until your program finishes, because breakpoints are (almost) never hit in compiled mode. The one exception to that are breakpoints in the current frame. See e.g.

julia> using Debugger

julia> foo(x) = begin
         y = 2x
         @bp
         z = x*y
         return x+y+z
       end
foo (generic function with 1 method)

julia> bar(x) = begin
         y = 5x
         @bp
         z = 2*foo(y)
         @bp 
         return 2*z
       end
bar (generic function with 1 method)

julia> @run bar(3)
Hit breakpoint:
In bar(x) at REPL[11]:1
 1  bar(x) = begin
 2    y = 5x
●3    @bp
>4    z = 2*foo(y)
●5    @bp 
 6    return 2*z
 7  end

About to run: (foo)(15)
# enter compiled mode here with `C`
1|debug> c 
Hit breakpoint:
In bar(x) at REPL[11]:1
 2    y = 5x
●3    @bp
 4    z = 2*foo(y)
●5    @bp 
>6    return 2*z
 7  end

About to run: (*)(2, 990)
1|debug> c
1980

julia> # the breakpoint in foo never got hit

Oh, that’s a shame… I need to look into MagneticReadHead again, then

I’m not aware of any such decision. When did this happen?

I didn’t think “Julia” supported any editors at all. But I do know that VS Code supports Julia, and that some people have made Julia plugins in other editors as well. It’s up to whomsoever wants to use a particular editor to help push Julia support further.

2 Likes

To add to @DNF’s answer, I don’t think JuliaLang itself decided anything. VSCode is the preferred IDE for most because Microsoft shifted resources away from Atom to VSCode and developers followed.

Yep, let’s say that Julia support in editor other than VSCode/Juno is not encomiable.

For instance, I use Vim and the syntax file breaks with other plugins. The language provider is a pain and autoformatting too, because they need to have plugins installed in the current environment but no “develop” section exists in the Project.toml.

But this should be another thread…