skip to Main Content

I have tried split up r-scripts using the syntax "source". The problem is that if script_a.r is using a function in script_b.r and I run script_a.r, the debugger will ignore any break point in source_b.r even though the code in source_b.r is run.

The only work-around I’ve found is writing "browser()" instead of a break point. While that may seem like just as good, it’s annoying. To stop it from halting there I have to remove that browser() line, save the source file again. Also, I’ve discovered that the debugger sometimes jump to the wrong part of the code, but maybe that’s another issue. Furthermore another thin I really like in VSC/Pythons debugging mode is that the debugger stops if there is an error/crash. When it stops I can see where it went wrong, inspect the other variables in the same scope and work from there. But maybe that’s another question also.

I’ve of course googled this but haven’t found that much. Maybe I’m using R/RStudio the wrong way? Maybe I shouldn’t be so reliant on the debugger? Or that I should test my own source-files more individually before using the in combination? Or maybe does it mean that r-scripts are not meant to be split up this way? That I’m better off using python instead?

Background: I’ve used R for almost 10 years, mostly for simple scripts that download data, make some simple calculations and write excel files or jpg-files with the results. I’m a statistician with no real programming knowledge and I’ve guess I’ve been programming quite sloppy, a lot of global variables, long functions, long scripts. Three years ago I started building a more complex (actuarial/pensions) model in Python. I started splitting my code up in a lot of differents files/modules and also tried to avoid global variables. I really liked this, it helped my process by reducing the cognitive load through a more limited scope. I also started to use the debugger a lot, because it’s an easy way to verify what’s happening inside all those functions and also viewing the call stack. Now I’m coming back to R again and want to bring some of those ideas with me.

UPDATE: When using Visual Studio Code it just seems to work debugging r-code split up into different r-files. I will probably switch to Visual Studio Code then since I already use that for Python.

2

Answers


  1. RStudio’s debugger often skips breakpoints in sourced files, which can be frustrating. A reliable workaround is using browser() in place of breakpoints, even though it’s less convenient. To ease debugging, wrap browser() in a conditional (e.g., if (debug_mode) browser()) so you can toggle it on or off. For error handling similar to Python, try options(error = recover), which stops execution on errors, letting you inspect variables. Testing functions independently and using unit tests (testthat) can also help manage split scripts more effectively.

    Login or Signup to reply.
  2. This is even less convenient than inserting "browser" calls, but you can use the setBreakpoint() function in R to set a breakpoint. RStudio won’t know about it so won’t show the red dot there or jump to the right location, but execution will pause at the right place.

    For example, if this is source_b.R:

    f <- function() {     # line 1
       print("line 2")    # line 2
       print("line 3")    # line 3
    }
    

    and this is source_a.R:

    f()
    

    then you can do the following:

    source("source_b.R")
    setBreakpoint("source_b.R#2")
    source("source_a.R")
    

    and the debugger will stop just before running line 2 of source_b.R, with text like this:

    source_b.R#2
    Called from: f()
    Browse[1]>
    

    It might be possible to use the rstudioapi package to make RStudio more aware of the underlying debugger state. For example, this function sets a breakpoint on the current line in the source editor:

    bp <- function(clear = FALSE) {
      ctxt <- rstudioapi::getSourceEditorContext()
      line <- ctxt$selection[[1]]$range$start["row"]
      if (clear)
        setBreakpoint(paste0(ctxt$path, "#", line), clear = TRUE)
      else
        setBreakpoint(paste0(ctxt$path, "#", line),
                      tracer = substitute({
                        rstudioapi::documentOpen(path, line)
                        browser()
                      }, list(path = ctxt$path, line = line)))   
    }
    

    and causes the editor to jump to that line if the breakpoint is hit, but RStudio ends up a little confused, and may switch to a different file after that. Maybe this could be fixed, or maybe you could write a similar function for some other editor.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search