16

Imagine I run an R script from the command line, like this:

Rscript prog.R x y z

and I want to examine the code at a certain line.

Presently, I can't just debug it interactively within RStudio because I don't know how to pass in the arguments.

As it is designed to be run from the command line, how can I debug the script via the command line / outside of RStudio?

Mus
  • 7,290
  • 24
  • 86
  • 130
Kashif
  • 3,063
  • 6
  • 29
  • 45
  • Rstudio does provide debugging tools. Can you write your whole script as a function in R and pass x y z as arguments to that function? – Dinesh.hmn Dec 05 '16 at 06:14
  • @Dinesh.hmn I reckon that the OP is interested in calling [tag:rstudio] debugging tools when the R script is called via `source` function. When executed via **Cmd + return** the RStudio enters debugging mode. This does not happen when the script is called via `source` function. – Konrad Dec 05 '16 at 08:05
  • 1
    Does your script get the arguments by calling `commandArgs()`? So you want a way of being able to "fake" command arguments when calling a script with `source` in RStudio? – Spacedman Dec 07 '16 at 08:39
  • 1
    Unfortunately unlike Visual Studio and VS Code there does not seem to be a way with RStudio to provide arguments to RScript that can be subsequently debugged in RStudio. After googling around, it seems to me that RStudio way of enabling debugging of scripts with arguments is to allow passing arguments in a config file https://cran.r-project.org/web/packages/config/vignettes/introduction.html – Sergei Nov 21 '17 at 22:43
  • Just a hunch, but have you added `browser()` to the line in the script you want to examine? Also, [here is a relevant question](https://stackoverflow.com/questions/57668869/is-there-a-way-to-debug-an-r-script-run-from-the-command-line-with-rscript-exe) on debugging from the terminal/cmd line. – Jessica Burnett Nov 24 '21 at 18:25
  • Thanks! I hadn't tried that but I'll do that next time I run into an issue. – Kashif Nov 25 '21 at 19:27

3 Answers3

3

If your only problem is passing command line arguments to a script in Rstudio, you can use the following trick.

Your script probably accesses the command line arguments with something like:

args <- commandArgs(trailingOnly = TRUE)

After which args contains a character vector with all the trailing command arguments, which in your example would be c("x", "y", "z").

The trick to make your code run in Rstudio without any changes is simply to define a local function commandArgs that simulates the arguments you want. Here I also take care of the case where trailingOnly = TRUE although it's rarely used in practice.

commandArgs <- function(trailingOnly = FALSE) {
    if (trailingOnly) {
        c("x", "y", "z")
    } else {
        c("Rscript", "--file=prog.R", "--args", "x", "y", "z")
    }
}

Once commandArgs is defined in the global environment, you can run your script in Rstudio and it will see "x", "y", "z" as its arguments.

You can even go one step further and streamline the process a bit:

#' Source a file with simulated command line arguments
#' @param file Path to R file
#' @param args Character vector of arguments
source_with_args <- function(file, args = character(0)) {
  commandArgs <- function(trailingOnly = FALSE) {
    if (trailingOnly) {
      args
    } else if (length(args)) {
      c("Rscript", paste0("--file=", file), "--args", args)
    } else {
      c("Rscript", paste0("--file=", file))
    }
  }
  # Note `local = TRUE` to make sure the script sees
  # the local `commandArgs` function defined just above.
  source(file, local = TRUE)
}

Let's imagine you want to run the following script:

# This is the content of test.R
# It simply prints the arguments it received.

args <- commandArgs(trailingOnly = TRUE)
cat("Received ", length(args), "arguments:\n")
for (a in args) {
  cat("- ", a, "\n")
}

This is the result with Rscript:

$ Rscript --vanilla path/to/test.R x y z
Received  3 arguments:
-  x 
-  y 
-  z 

And you can run the following in R or Rstudio:

source_with_args("path/to/test.R")
#> Received  0 arguments:

source_with_args("path/to/test.R", "x")
#> Received  1 arguments:
#> -  x

source_with_args("path/to/test.R", c("x", "y", "z"))
#> Received  3 arguments:
#> -  x 
#> -  y 
#> -  z
asachet
  • 6,620
  • 2
  • 30
  • 74
0

This solution may solve your problem: Is there a way to debug an R script run from the command line with Rscript.exe - Answer

ipdb.r <- function(){
  input <- ""
  while(!input %in% c("c","cont","continue"))
  {
    cat("ipdb.r>")
    # stdin connection to work outside interactive session
    input <- readLines("stdin",n=1)
    if(!input %in% c("c","cont","continue","exit"))
    {
      # parent.frame() runs command outside function environment
      print(eval(parse(text=input),parent.frame()))
    }else if(input=="exit")
    {
      stop("Exiting from ipdb.r...")
    }
  }
}
jpd527
  • 1,543
  • 1
  • 14
  • 30
0

For hacking commandArgs(), it's also possible to just overwrite the base::commandArgs() with your own version instead of masking it, since the base environment comes unlocked.

For the part of your question on debugging, you can perform traceback() as usual with any source()d scripts. Also just want to refer to this function dump.frames(). Through this function you can dump the stracktrace to a file at error and look at it later.

Siqi Zhang
  • 51
  • 4