36

I want to step through an R script. I saw the "debug" command while searching for how to do this but that seems to only apply to functions. This script doesn't have any functions.

The "browser" command looked promising so I put "browser()" as the first line of my script but it didn't seem to do anything when I ran it.

How do I get the script to pause on the first line so I can step through it?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Greg
  • 45,306
  • 89
  • 231
  • 297

6 Answers6

23

I was racking my brain trying to figure this out (stepping through a script without a specific function to call) in RStudio's IDE Version 0.98.1102.

Solution for a new script in RStudio:

  1. Create a new R script (ctrl+shift+n)
  2. Enter code in the file
  3. Set a break point by
    • a) clicking left of the code line number where you want to set a break point (red dot) or
    • b) adding browser() to the code line where you want to set a break point
  4. Save the file
  5. Enter debugging mode and source the file by
    • a) checking the Source on Save box (above the Source window) and then saving the file,
    • b) clicking the Source button at the top-right of the Source window,
    • c) entering debugSource("<yourfilename>") + enter in the Console, or
    • d) entering ctrl+shift+s
  6. Go through the debugging process

For more steps on debugging in RStudio, see this help file (dated April 23, 2015 12:59).

Daniel Fletcher
  • 1,165
  • 4
  • 13
  • 23
9

I'm partial to RStudio, so I recommend the following:

  1. Download RStudio
  2. Open your R Script
  3. put your cursor on the first line
  4. click ctrl + enter (PC/Linux) or command + return (Mac)
  5. repeat!

A nice feature of RStudio is that RStudio server can run great on a headless server. You then connect to the server via http in a web browser on your local machine. I use this configuration when running R on EC2 instances. RStudio maintains state so if I lose internet access on my train ride, when I get signal back RStudio picks up exactly where I left off and my remote machine has no idea that I disconnected and reconnected. Note that RStudio server is currently only supported on FC/CentOS and Debian/Ubuntu. Although it may compile under other variants of *nix.

JD Long
  • 59,675
  • 58
  • 202
  • 294
8

One popular way is to do this from your 'IDE' or editor -- Emacs / ESS do it very well, others do it too.

The basic idea is that you send either the line under the cursors, or function, or block, ... to the associated R process. Several other editors support this, including RStudio. My preference is still with ESS, but I am sure you can find something suitable.

Lastly, browser() et al can do that from within the R process but it is a little less pointy-clickety. Read the documentation, or books like Chambers "Software for Data Analysis" (Springer, 2008).

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 2
    I don't have an IDE. I'm just running Rscript . Is there a way to break into the debugger from there? – Greg Sep 20 '11 at 14:16
  • What my answer was trying to suggest to you is that you either get an IDE, or really read up on browser(). – Dirk Eddelbuettel Sep 20 '11 at 14:21
  • 1
    Thanks. I found this the documentation for browser. It just says it will halt excecution and provide the user with a prompt. So I guess the question is Why wouldn't it be doing that for me? http://cran.r-project.org/doc/manuals/R-lang.html#browser – Greg Sep 20 '11 at 14:26
  • `browser()` only works when you're running R interactively—that is, you run `R` from your shell, and inside R you `source('myscript.r')` where `myscript.r` has a `browser()` statement inside it. It won't do anything if you run the script non-interactively, as `Rscript myscript.r` does. – jimjamslam Apr 22 '16 at 01:11
6

For an R only solution, which evaluates complete expressions rather than individual lines, try this:

sourcep <- function(file){
  coms <- parse(file)
  for (i in seq_along(coms)){
    print(coms[[i]])
    eval(coms[[i]],envir=.GlobalEnv)
    mess <- paste("Expression",i,"of",length(coms),"parsed. Press <return> to continue.")
    cat(mess)
    readLines(n=1)
  }
}

You call this as you would call source (though this is much more basic and doesn't include any of its options). Basically, it uses parse to create a list of the parsed, but unevaluated expressions from your source file, then iterates through this list to print the expression, evaluate it in the global environment and then put a message to indicate the progess. The final line is the one that creates the pausing: a call to read a single line from stdin().

James
  • 65,548
  • 14
  • 155
  • 193
  • Thanks this looks promising. Could you explain what it's doing? And also where do I put this to run it? Inside my existing file? – Greg Sep 20 '11 at 14:43
  • @Greg OK, put a description in now. You would have to define this before calling it, so possibly `source`d from a separate file, or in your .Rprofile. – James Sep 20 '11 at 14:56
  • Thanks. Any chance you could also show how I would call it? I see that sourcep is the function, but what do I use as the argument to the function? – Greg Sep 20 '11 at 15:01
  • The name of the file you would be sourcing, eg `sourcep("myfile.r")` – James Sep 20 '11 at 15:03
  • Oh also, the rscript I want to step through takes command line arguments. Is there a way to pass those in? – Greg Sep 20 '11 at 15:08
  • How are you calling it at the moment? – James Sep 20 '11 at 15:16
  • I called it like so: Rscript myfile.R -d somedir -i somename ... and so on. I think the script reads the args with "opts <- getopts()" – Greg Sep 22 '11 at 13:05
  • 1
    Rscript is really meant for non-interactive use, you might want to use R interactively while you debug your file – James Sep 22 '11 at 13:44
5

You mention in a comment that you run your code with Rscript, but to debug you need to run it interactively. In other words, to get browser to "work", start up a regular R console and source your script. Since the first line of the script is browser(), you'll immediately get back to the prompt, at which you can use "n" to single step through the code. But, since it's a full-blown R prompt, you can also check or change any variable value just by typing its name or assigning to it. (Or indeed, invoke arbitrary R functions.)

Davor Cubranic
  • 1,051
  • 10
  • 16
4

As suggested in another answer, inserting browser() at the beginning of your script, getting an interactive session by running R rather than Rscript, and then using source('myscript.Rscript') from R will do the trick if your script does not require commadline arguments (e.g. like those processed by argparse).

If you do need to run with commandline args, you can simply invoke R with the --args options (e.g. R --no-restore --no-save --args <your commandline args here>) and the sourced script will see the arguments as if it had been invoked using Rscript. There are other solutions to the question of how to pass commandline args to source, but they don't target this specific use case where source will be called only once.

teichert
  • 3,963
  • 1
  • 31
  • 37