1

I am attempting to write error messages for my script to a log file. It works when I do:

test <- file("error_file.log", open = "wt")
sink(test, type = "message")
try(data <- read.delim("genes2.txt",
                   header = TRUE,
                   as.is = TRUE))
sink(type = "message", append = TRUE)
close(test)

However, when I add an additional component to the script, it does not append both error messages. In this case both input files do not exist and should give a "no such file directory" for each file. Here is my attempt for both input files:

enter code heretest <- file("error_file.log", open = "wt")

sink(test, type = "message")

try(data <- read.delim("genes2.txt",
                       header = TRUE,
                       as.is = TRUE))

sink(type = "message", append = TRUE)
close(test)

test2 <- file("error_file.log", open = "wt")
sink(test2, type = "message")

try(variables <- read.delim("Book3.txt",
                            header = TRUE, 
                            as.is = TRUE,
                            check.names = FALSE,
                            text = TRUE,
                            na.strings = c("", NA)))

sink(type = "message", append = TRUE)
close(test2)

Thank you!

P.s. would it be possible to customize my own error messages for each try()?

2
  • Use tryCatch instead of try to catch and replace the error message, e. g.: tryCatch(stop("stupid msg"), error = function(e) { if (grepl("stupid msg", e$message, fixed = TRUE)) print("clever msg") else print(e$message)}). The risky part is that other R installations might emit error messages in different languages than English... Commented Dec 20, 2017 at 6:38
  • Could you perhaps give this example in the context of my script above. I am not sure where to place which function. Thank you! Commented Dec 21, 2017 at 7:12

2 Answers 2

1

Try using this, it'll append both the messages to error_file.log:-

test <- file("error_file.log", open = "wt")
sink(test, append = TRUE, type = "message")


try(data <- read.delim("genes2.txt",
                       header = TRUE,
                       as.is = TRUE))


try(variables <- read.delim("Book3.txt",
                            header = TRUE, 
                            as.is = TRUE,
                            check.names = FALSE,
                            text = TRUE,
                            na.strings = c("", NA)))


sink(type = "message")

So, error file would have:-

Error in file(file, "rt") : cannot open the connection
In addition: Warning message:
In file(file, "rt") :
  cannot open file 'genes2.txt': No such file or directory
Error in file(file, "rt") : cannot open the connection
In addition: Warning message:
In file(file, "rt") :
  cannot open file 'Book3.txt': No such file or directory

I hope this solves your problem.

The trick is just open your log file and sink once in the begining. And, close sink in the end.

Sign up to request clarification or add additional context in comments.

4 Comments

Strange, when I tried that approach it did not work, now it does. Welcome to programming I guess. Do you have an idea for custom messages?
Please accept answer if it solved your problem. Custom messages as in?
Sorry about that. Instead of the whole: In file(file, "rt") : cannot open file 'Book3.txt': No such file or directory. I would make the error something like: "Please check your input file". into the error_file.log.
If I understand it correctly, you would need gsub to customize your messages.
0

Using the valid answer of @suchait as basis you can customize your error message this way:

test <- file("error_file.log", open = "wt")
sink(test, append = TRUE, type = "message")

tryCatch(data <- read.delim("genes2.txt", header = TRUE, as.is = TRUE),
         error = function(e) {
           # replace one specific error message with another one
           if (grepl("cannot open", e$message, fixed = TRUE))
             # using "message" instead of "print" since you are sinking into type "message" (not "output")
             message("Customized error message 1: The file could not be opened\n")
           else
             message(e$message)
         }
         # If you wanted to replace the warnings too you will run into big problems:
         # tryCatch stops the execution and the error handler above is never called
         # causing the log to be empty. Conclusion: Don't reinvent the wheel and
         # use a suitable logging framework (e. g. the package "futile.logger")...
         # , warning = function(w) {return("Warning ignored...")}  # ignore warnings
)

tryCatch(variables <- read.delim("Book3.txt", header = TRUE, as.is = TRUE, check.names = FALSE, text = TRUE, na.strings = c("", NA)),
         error = function(e) {
           # Always write your specific error message (+ the original message if you want)
           message(paste("Customized error message 2: The file could not be opened. Details:", e$message, "\n"))
         }
)

sink(type = "message")

If you wanted to replace the warnings too you will run into problems (see my comments in the code above) and the solution would be an even more complicated code (using withCallingHandlers + try)

Therefore I think it is better to use an existing logging framework like the package futile.logger (see function ftry) instead of reinventing the wheel and running into many problems. You can set the "severity level" then to log e. g. only errors but no warnings...

tryCatch is a beast in R if you want to combine error handling with logging (see R: Catch errors and continue execution after logging the stacktrace (no traceback available with tryCatch) for details and a long list of related SO questions)...

If you want to add automatic logging to try and tryCatch you could use the package tryCatchLog (https://github.com/aryoda/tryCatchLog). For compliance reasons: I am the author of the package...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.