Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make execution stop on error in RStudio / Interactive R session

Tags:

When executing a block of code in RStudio, execution doesn't actually stop when an error occurs. For example, if I have the following code in the open editor:

x <- 'test'
stopifnot(is.numeric(x))
print('hello world')

And run it (either with command-return or by clicking the "Run" button), it prints the error but then marches on and executes the print statement.

Is there a way to configure RStudio to not proceed past the error? i.e. make it stop at line 2 above and not proceed to the print statement?

EDIT: Just realized this also happens if I'm sending blocks of code in the standard R GUI using command-R.

like image 729
nick_eu Avatar asked Feb 15 '17 17:02

nick_eu


People also ask

How do you stop an execution in RStudio?

However, if you are using RStudio on a Windows computer, you can usually use Esc to stop a currently executing R script. Then, we can press Esc to interrupt the loop.

How do you stop a command in R console?

If you're using R from the command line instead of from within RStudio, you need to use Ctrl + C instead of Esc to cancel the command.


2 Answers

One way to solve this is to configure the R 'error' option to run a custom function when an error is encountered.

An example error-handling function can pause execution of R using Sys.sleep and await user input (for instance, breaking-out of the running function by pressing ctrl-C, or Escape in R-Studio on my Mac).

Normally, R will then move-on and execute any subsequent commands. However, we can prevent this by defining a function that will 'eat' all of these so that they don't get run. To make this slicker-still, we can output a 'cursor up' character sequence after each 'eaten' line, which erases each of them as the next one is output, so that the not-run lines don't clutter up the terminal/console.

Example code:

# Define our error-handling pause function:

pause=function(){
    on.exit(eat_input())
    cat("Paused: press ctrl-C (or Escape key in Rstudio) to continue\n")
    cat("(any subsequent code will be ignored)\n")
    Sys.sleep(Inf)
}

# Define our 'eat_input' function to prevent output of subsequent, not-run input:

eat_input=function(){
    cat("\033[1A")
    while((x=readline())!='')cat("\033[1A")
}

# Set the 'error' option to execute our pause function:

options(error=pause)

Try it out:

print("Before the error")

# an error: we want to stop after this
xxx

# some more input: we don't want this to be run or to appear in the console
print("After the error")

To switch-off this behaviour, just re-set the error option to NULL:

options(error=NULL)
like image 53
Dominic van Essen Avatar answered Sep 22 '22 23:09

Dominic van Essen


I don't think that there is a way to prevent RStudio from running all the lines, when you select a section and press Ctrl+Enter. Rstudio is just running one line after the other. Even if stopifnot() is called inside of a function, all the lines after that function call will still be evaluated.

If your goal is simply to be informed when something goes wrong, before a lot of code is run in vain, maybe you could define a function similar to stopifnot() that will just go into an endless loop, if there is an error. You could then press Esc or the Stop-Button in RStudio to interrupt the program. Something like this:

waitifnot <- function(cond) {
  if (!cond) {
    message(deparse(substitute(cond)), " is not TRUE")  
    while (TRUE) {}
  }
}

Now, you can run your example code with this function:

x <- 'test'
waitifnot(is.numeric(x))
print('hello world')

As expected, hello world is never printed. You will get an error message, telling you that something went wrong, and then the program will wait until you abort it manually.

This won't work well in any situation other than interactive mode. To avoid unpleasant situations, you could also let the function react differently, if it is not used in interactive mode, for instance like this:

waitifnot <- function(cond) {
  if (!cond) {
    msg <- paste(deparse(substitute(cond)), "is not TRUE")
    if (interactive()) {
      message(msg)
      while (TRUE) {}
    } else {
      stop(msg)
    }
  }
}

This function will go into an endless loop only if run in interactive mode. Otherwise, it will simply abort execution by calling stop(). I have checked that this works as expected with Ctrl+Enter or the Source button in RStudio (endless loop) and with Rscript on the Bash command line (abort of the program).

like image 38
Stibu Avatar answered Sep 19 '22 23:09

Stibu