Search code examples
rtry-catch

Save txt file with error, condition specific


I have some R code that looks like this:

###Set base path for onedrive folder
basepath<-sprintf('C:/Users/%s/OneDrive - Company/General/PowerBI New/', Sys.info()[["user"]])

cat('filepath0 0_Views')
#0_Views
filepath0<-paste0(basepath,'0_Views/Views pull_20230411.R')
RunScript2(filepath0)
#clear the environment except for the base path
rm(list=ls()[! ls() %in% c("basepath","RunScript2")])


cat('filepath2 #monthly accrual report')
#monthly accrual report 
filepath2<-paste0(basepath, 'ONC - OPS - Monthly Accrual Report/ONC- Ops- Monthly Accrual Report 20221007.R')
RunScript2(filepath2)
#clear the environment except for the base path
rm(list=ls()[! ls() %in% c("basepath","RunScript2")])


cat('filepath3 #protocol dashboard')
#protocol dashboard
filepath3<-paste0(basepath, 'ONC -OPS - Protocol Dashboard/ONC-Ops-Protocol Dashboard.R')
RunScript2(filepath3)
 #clear the environment except for the base path
rm(list=ls()[! ls() %in% c("basepath","RunScript2")])

Basically: it has a parent directory, and then in 9 little chunks of code (3 pictured) it'll run a different R file. It says Runscript2() instead of source() because I'm working on a trycatch function.

For the trycatch, I WANT to save the error output to one location, with a description of what the error was, and ideally which file failed.

Right now I have this:

outputFile <-file("output.txt")
RunScript2 <- function(x){
  tryCatch(
    {
      result = source(x) 
      return(result)
    },
    error=function(e) {
      message('An error occurred')
      writeLines(as.character(e), outputFile)
    },
    warning=function(w) {
      message('A warning occurred')
      writeLines(as.character(w), outputFile)
    }
  )
}


close(outputFile)

The problem is, right now the output.txt file is created and stored in random locations (depending on what filepath was recently used) and I'd love to always put it in one set location (lets say a new subfolder of the main path called "errors". The other problem is that while it will record what the error was, I cant tell if it happened in Views pull_20230411.R or ONC-Ops-Protocol Dashboard.R or.... And lastly if no error happened, and no file was ever created, then the close(outputfile) itself errors.

Could anyone help?

Update based on some comments/suggestions

I'd prefer not to use a new package if possible. Several users will run this and I'd rather not require installations.

Also, I noticed something when testing a suggested answer. Lets say there is a serious error in the second chunk of code, and then just a warning in the next chunk of code. The script right now will write the 'output.txt' with the first error, and then immediately write over it with the next warning.

I supposed there's two ways to solve this (either write both into the file, or write two files). Writing two files in this case would be preferable, with different names.


Solution

  • You can try something similar to this:

    
    RunScript2 <- function(x){
      basepath <- sprintf('C:/Users/%s/OneDrive - Company/General/PowerBI New/', Sys.info()[[ 'user' ]])
      setwd(basepath) # approach 1: go back to the basepath each time
      # outputFile <- file(file.path(basepath, 'output.txt')) # approach 2: explicitly specify the full path to the output.txt file
      outputFile <- file('output.txt')
      tryCatch(
        {
          result = source(x) 
          return(result)
        },
        error = function(e) {
          message('An error occurred in source file ', x)
          writeLines(sprintf('%s: %s', x, as.character(e)), outputFile)
        },
        warning = function(w) {
          message('A warning occurred in source file ', x)
          writeLines(sprintf('%s: %s', x, as.character(w)), outputFile)
        }
      )
    }