Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sink does not release file

Tags:

r

sink

I know that the sink() function can be used to divert R output into a file, e.g.

sink('sink-closing.txt')
cat('Hello world!')
sink()

Is there a simple command to close all outstanding sinks?

Below, I elaborate on my question.

Suppose that my R-script opens a sink() in an R-script, but there is an error in the R-script which occurs before the script closes the sink(). I may run the R-script multiple times, trying to fix the error. Finally, I want to close all the sinks and print to the console. How do I do so?

Finally, in the interest of concreteness, I provide a MWE to illustrate the problem I face.

First, I write an R-script sink-closing.R which has an error in it.

sink('sink-closing.txt')

foo <- function() {
  cat(sprintf('Hello world! My name is %s\n', 
              a.variable.that.does.not.exist))
}

foo()

sink()

Next, I source the R-script multiple times, say 3 times by mistake as I try to find and fix the bug.

> source('~/Dropbox/cookbook/r-cookbook/sink-closing.R')
Error in sprintf("Hello world! My name is %s\n", a.variable.that.does.not.exist) : 
  object 'a.variable.that.does.not.exist' not found

Now, suppose that I am debugging the R-script and want to print to the console. I can call sink() multiple times to close the earlier sinks. If I call it 3 times, then I can finally print to the console as before. But how do I know how many sinks I need to close?

like image 815
I Like to Code Avatar asked Sep 10 '13 23:09

I Like to Code


People also ask

What does sink () do in R?

The sink() function in R drives the R output to the external connection. You can export the data in multiple forms such as text and CSV files. You can either print the data into the connection or directly export the entire data to it. After the data transfer, you can unlink the connection to terminate the file.

How do I exit a sink in R?

exit(sink()) . This will close the sink "when the current function exits (either naturally or as the result of an error)" (documentation here). So we create the sink, tell R to close it when it exits, and then execute the code that might error. This will close the sink regardless of whether the code errors or not.


3 Answers

closeAllConnections()   # ......................... 
like image 123
IRTFM Avatar answered Sep 23 '22 23:09

IRTFM


You can use sink.number() to tell you how many diversions are already set and then call sink that many times. Putting it into a function you could have this

sink.reset <- function(){     for(i in seq_len(sink.number())){         sink(NULL)     } } 
like image 20
Dason Avatar answered Sep 26 '22 23:09

Dason


Based on @mnel's comment:

sinkall <- function() {
  i <- sink.number()
  while (i > 0) {
    sink()
    i <- i - 1
  }
}

Should close all open sinks.

You may also encounter this problem when dealing with devices and plots, where the number of open devices isn't reported anywhere. For a more general case you could use this:

stopWhenError <- function(FUN) {
  tryCatch({
    while(TRUE) {
      FUN()
    }
  }, warning = function(w) {
    print("All finished!")
  }, error = function(e) {
    print("All finished!")
  })
}

stopWhenError(sink) # for sink.
stopWhenError(dev.off) # close all open plotting devices.

EDIT: sink throws a warning not an error so I've modified the code so that it won't run forever, whoops!

like image 29
Scott Ritchie Avatar answered Sep 25 '22 23:09

Scott Ritchie