Stopping R code execution upon error when run as non-interactive Rscript - r

How do I get an R (version 3.4.2, CentOS 6.9) script to stop on Error instead of happily continuing on? My file :
$ cat tmp.R
a = 9
print(a)
print(b)
print(d)
print("Should never get here")
Running tmp.R non-interactively it:
$ Rscript tmp.R
Looking for libraries in : ~/.R/3.4.2-lib
[1] 9
Error in print(b) : object 'b' not found
Error in print(d) : object 'd' not found
[1] "Should never get here"
Question : How do I get R to stop execution upon encountering an error?
I've tried things like options(error=stop) and options(error=browser) which work in the interactive case but not non-interactive Rscript example.

This is because I have set options(error=traceback) in my .Rprofile. Commenting it out in my .Rprofile leads to code termination at line 3 as expected. This raises issues with why this generates output. See related questions this and this.

Related

R: What causes "In eval(ei, envir) : NAs introduced by coercion"?

I sometimes get the following warning in my R code output:
Warning message:
In eval(ei, envir) : NAs introduced by coercion
This happens only when running my R code with R --slave --file=/path/to/sourcecode.R --args arg1 arg2 arg3 arg4 or Rscript /path/to/sourcecode.R arg1 arg2 arg3 arg4 but not when running the code interactively (not even if I run it in an interactive R session on a cluster node).
I cannot provide example code to reproduce the problem because this is a large project with a lot of code spread across several files, and I'm not sure what specific code or circumstances are triggering it.
Googling the error, I found references to an error message referencing "eval(ei, envir)" that happens when you call source from inside of a function . The message I get is different - the post in the link is an error about not being able to find a variable, mine is a warning about NAs being introduced by coercion. So it's probably not the same problem, but I suspect it is somehow still related to using source(), because my code also uses source().
If I knew what "ei" was and why using source() apparently involves calling eval(ei,envir), that might help me figure out what exactly (an environment variable? which one?) has something in it that would trigger an "NAs introduced by coercion" message... does anyone have any ideas what might be going on here?
I have figured out what was causing this. Since Google searches did not find any exact matches for this message, I'm making a Q&A-style post in hopes it will help the next person to Google this particular error.
The warning happens when a variable or other object created in your main code contains values that get coerced to NA in code that you have loaded via source(). Here is some example code to cause it:
test1.R:
print("Starting test1.R")
x <- c('3','bicycle','5')
source('test2.R')
print('Finished test1.R.')
test2.R:
print("Starting test2.R")
y <- as.numeric(x)
print("Finished test2.R")
The output of Rscript test1.R is:
[1] "Starting test1.R"
[1] "Starting test2.R"
[1] "Finished test2.R"
Warning message:
In eval(ei, envir) : NAs introduced by coercion
[1] "Finished test1.R."
Note that even though the line that triggers the error happens in the middle of the code loaded with source(), you don't see the warning in your output until after the code loaded by source() has finished.
You also don't have to be running in batch mode for it to happen. Here I use source() in interactive mode to cause the same message:
> x <- c('3','bicycle','5')
> source('test2.R')
[1] "Starting test2.R"
[1] "Finished test2.R"
Warning message:
In eval(ei, envir) : NAs introduced by coercion
So why was this only happening in batch mode in my original problem? It turned out to be a red herring... when I ran my code in interactive mode, I created a vector to simulate command-line arguments, like this: args <- c('/path/to/infile','27',NA,'0.1'). But when my code was running in batch mode, it created the vector "args" like this: args <- commandArgs(trailingOnly=T). And an NA passed as a command line argument is not a real NA, it is the string 'NA'. So as.numeric('NA') coerces 'NA' to NA. But the argument was only 'NA' instead of NA when running in batch mode.
Those two quirks combined were enough to cause a troubleshooting nightmare that cost me a whole evening. Hopefully this Q&A-style post will save the next person to Google this error message some time!

Is there a function in R to check if there is an error in r script or in a log?

I'm trying to create an if statement to check whether there is any errors in my R script (or error displayed on the console) and also log files if there are to have "error" in a variable and if there isn't to have "no error" in the same variable.
I looked at is.error() however I want to check if an error is shown on the console or log file.
There is no single-stop solution to the best of my knowledge. There are several things you can try:
1) Incorporate your script into your code and use tryCatch or try to catch any errors. More information on error catching and debugging in R can be found here.
2) Execute your script in the system shell via the system command and inspect output caught by setting intern=TRUE.
You can source the script in a new environment :
testscript <- function(scriptpath) {
tryCatch({
# Tests is the script runs without error
source(scriptpath, local = new.env())
message("Script OK")
},
error = function(cond){
message('Script not OK')
message(cond)
})}
for example, content of script.R :
x <- 1
y <- 2
x + z
testscript('script.R')
Script not OK
object 'z' not found

Running R function with arguments in 32 bit R, inside 64 bit R

Suppose I want to run the function
test.function <- function(arg1){
print(arg1)
}
How can I run, lets say:
test.function("Hello world")
in 32 bit mode, using 64 bit R? I have managed running an entire script in 32 bit mode using
system(paste0(Sys.getenv("R_HOME"), "/bin/i386/Rscript.exe ",'"some_script.R"'))
But how can I change this, so that it can run a function with arguments, instead of an entire script?
EDIT
Following the answer by Roman Luštrik and running
system('Rscript test.script.R "hello"')
Gives me the following error:
Error in winDialog(type = "ok", message = message_text) :
winDialog() cannot be used non-interactively
call: -> check.for.updates.R -> winDialog
Running stopped
Warning message:
running command 'Rscript test.script.R "hello"' had status 1
(The error message was in my native language, so I had to translate a few words, so the text might differ slightly on other systems)
You can't run a specific function only, you will have to create a script. This does not stop you from creating a one-function only script, though.
If you create a script called test.script.R and put it somewhere where you can find it.
args <- commandArgs(trailingOnly = TRUE)
str(args)
test.function <- function(x) {
message("Your input:")
message(x)
}
invisible(sapply(args, test.function))
Open up a terminal window. You can use Windows' cmd.exe (press Windows key and type cmd.exe or Command Prompt or whatever you have in your perhaps localized version of the system). Navigate to where the script is located and run it using the below command.
$ Rscript test.script.R "hello" "hello" "won't you tell me your name" "i hate the doors"
chr [1:4] "hello" "hello" "won't you tell me your name" ...
Your input:
hello
Your input:
hello
Your input:
won't you tell me your name
Your input:
i hate the doors
Or, you could use system to do the same thing through R.
system('Rscript test.script.R "hello" "hello" "won't you tell me your name" "i hate the doors"')
Notice the way I use single and double quotes. Single quotes are on the outer side. This call also assumes the script is located in the workspace where R is currently looking. You can change that using setwd(), though.
I managed to find a solution myself, by modifying Roman Luštrik's solution.
Following his example we have the script called test_script.R:
args <- commandArgs(trailingOnly = TRUE)
test.function <- function(x) {
print(x)
}
args.run <- list(x = args)
mydata <- do.call(test.function, args = args.run)
save(mydata, file = "Data.Rda") # If you need the output to an R object
Then in another script that runs 64 bit R, we can run this function in 32 bit R by:
pathIn32BitRScript <- '"C:/Some path/test_script.R"'
system(paste0(Sys.getenv("R_HOME"), "/bin/i386/Rscript.exe", pathIn32BitRScript, " ", "Hello world") )
load("Data.Rda") # Loads the results into an object called mydata
invisible(file.remove("Data.Rda")) # Deletes the file we created
In this example we have x = "Hello World". In case you have spaces in your path you will need the double quotes as I have in this example.

Fatal Error while using Rcpp in RStudio on Windows

I'm trying to use Rcpp on Windows in RStudio. I have R version 3.2.3 and I have installed the Rcpp package. The problem is that I am unable to call any functions defined through the CPP code. I tried the following (picked up from an example online).
body <- '
NumericVector xx(x);
return wrap( std::accumulate( xx.begin(), xx.end(), 0.0));'
add <- cxxfunction(signature(x = "numeric"), body, plugin = "Rcpp")
This gives the following warning, but completes execution successfully.
cygwin warning:
MS-DOS style path detected: C:/R/R-32~1.3/etc/x64/Makeconf
Preferred POSIX equivalent is: /cygdrive/c/R/R-32~1.3/etc/x64/Makeconf
CYGWIN environment variable option "nodosfilewarning" turns off this warning.
Consult the user's guide for more details about POSIX paths:
http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
When I try to use the above function,
x <- 1
y <- 2
res <- add(c(x, y))
I get the following error :
R Session Aborted
R encountered a fatal error.
The session was terminated.
Any suggestions? This same 'Fatal Error' happens for any code that I run with Rcpp.
Try rebuilding locally, starting with Rcpp. This is valid code and will work (and the hundreds of unit tests stress may more than this). Sometimes the compiler or something else changes under you and this sort of thing happens. It is then useful to have an alternative build system -- eg via Travis at GitHub you get Linux for free.
Also, learning about Rcpp Attributes. Your example can be written as
R> library(Rcpp)
R> cppFunction("double adder(std::vector<double> x) { return std::accumulate(x.begin(), x.end(), 0.0); }")
R> adder(c(1,2))
[1] 3
R>
which is simpler. Works of course the same way with Rcpp::NumericVector.

tryCatch does not catch an error if called though RScript

I'm facing a strange issue in R.
Consider the following code (a really simplified version of the real code but still having the problem) :
library(timeSeries)
tryCatch(
{
specificWeekDay <- 2
currTs <- timeSeries(c(1,2),c('2012-01-01','2012-01-02'),
format='%Y-%m-%d',units='A')
# just 2 dates out of range
start <- time(currTs)[2]+100*24*3600
end <- time(currTs)[2]+110*24*3600
# this line returns an empty timeSeries
currTs <- window(currTs,start=start,end=end)
message("Up to now, everything is OK")
# this is the line with the uncatchable error
currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA
message("I'm after the bugged line !")
},error=function(e){message(e)})
message("End")
When I run that code in RGui, I correctly get the following output:
Up to now, everything is OK
error in evaluating the argument 'i' in
selecting a method for function '[<-': Error in
as.POSIXlt.numeric(time(currTs)) : 'origin' must be supplied
End
Instead, when I run it through RScript (in windows) using the following line:
RScript.exe --vanilla "myscript.R"
I get this output:
Up to now, everything is OK
Execution interrupted
It seems like RScript crashes...
Any idea about the reason?
Is this a timeSeries package bug, or I'm doing something wrong ?
If the latter, what's the right way to be sure to catch all the errors ?
Thanks in advance.
EDIT :
Here's a smaller example reproducing the issue that doesn't use timeSeries package. To test it, just run it as described above:
library(methods)
# define a generic function
setGeneric("foo",
function(x, ...){standardGeneric("foo")})
# set a method for the generic function
setMethod("foo", signature("character"),
function(x) {x})
tryCatch(
{
foo("abc")
foo(notExisting)
},error=function(e)print(e))
It seems something related to generic method dispatching; when an argument of a method causes an error, the dispatcher cannot find the signature of the method and conseguently raises an exception that tryCatch function seems unable to handle when run through RScript.
Strangely, it doesn't happen for example with print(notExisting); in that case the exception is correctly handled.
Any idea about the reason and how to catch this kind of errors ?
Note:
I'm using R-2.14.2 on Windows 7
The issue is in the way the internal C code implementing S4 method dispatch tries to catch and handle some errors and how the non-interactive case is treated in this approach. A work-around should be in place in R-devel and R-patched soon.
Work-around now committed to R-devel and R-patched.
Information about tryCatch() [that the OP already knew and used but I didn't notice]
I think you are missing that your tryCatch() is not doing anything special with the error, hence you are raising an error in the normal fashion. In interactive use the error is thrown and handled in the usual fashion, but an error inside a script run in a non-interactive session (a la Rscript) will abort the running script.
tryCatch() is a complex function that allows the potential to trap and handle all sorts of events in R, not just errors. However by default it is set up to mimic the standard R error handling procedure; basically allow the error to be thrown and reported by R. If you want R to do anything other than the basic behaviour then you need to add a specific handler for the error:
> e <- simpleError("test error")
> tryCatch(foo, error = function(e) e,
+ finally = writeLines("There was a problem!"))
There was a problem!
<simpleError in doTryCatch(return(expr), name, parentenv, handler): object 'foo'
not found>
I suggest you read ?tryCatch in more detail to understand better what it does.
An alternative is to use try(). To modify your script I would just do:
# this is the line with the uncatchable error
tried <- try(currTs[!(as.POSIXlt(time(currTs))$wday %in% specificWeekDay),] <- NA,
silent = TRUE)
if(inherits(tried, "try-error")) {
writeLines("There was an error!")
} else {
writeLines("Everything worked fine!")
}
The key bit is to save the object returned from try() so you can test the class, and to have try() operate silently. Consider the difference:
> bar <- try(foo)
Error in try(foo) : object 'foo' not found
> bar <- try(foo, silent = TRUE)
> class(bar)
[1] "try-error"
Note that in the first call above, the error is caught and reported as a message. In the second, it is not reported. In both cases an object of class "try-error" is returned.
Internally, try() is written as a single call to tryCatch() which sets up a custom function for the error handler which reports the error as a message and sets up the returned object. You might wish to study the R code for try() as another example of using tryCatch().

Resources