Раковина не выпускает файл

Я знаю что sink() функция может использоваться для перенаправления вывода R в файл, например

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

Есть ли простая команда закрыть все выдающиеся раковины?

Ниже я уточняю свой вопрос.

Предположим, что мой R-скрипт открывает sink() в R-скрипте, но есть ошибка в R-скрипте, которая происходит до того, как скрипт закрывает sink(), Я могу запустить R-скрипт несколько раз, пытаясь исправить ошибку. Наконец, я хочу закрыть все раковины и распечатать на консоли. Как мне это сделать?

Наконец, в интересах конкретности, я предоставляю MWE, чтобы проиллюстрировать проблему, с которой я сталкиваюсь.

Сначала я пишу R-скрипт sink-closing.R в котором есть ошибка.

sink('sink-closing.txt')

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

foo()

sink()

Далее я source R-скрипт несколько раз, скажем 3 раза по ошибке, когда я пытаюсь найти и исправить ошибку.

> 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

Теперь предположим, что я отлаживаю R-скрипт и хочу вывести его на консоль. я могу позвонить sink() несколько раз, чтобы закрыть более ранние раковины. Если я вызову его 3 раза, то смогу наконец распечатать на консоль, как и раньше. Но как мне узнать, сколько раковин мне нужно закрыть?

4 ответа

Решение

Ты можешь использовать sink.number() сказать, сколько диверсий уже установлено, а затем позвонить sink это много раз. Поместив это в функцию, вы могли бы иметь это

sink.reset <- function(){
    for(i in seq_len(sink.number())){
        sink(NULL)
    }
}
closeAllConnections()   # .........................

Основано на комментарии @mnel:

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

Следует закрыть все открытые раковины.

Вы также можете столкнуться с этой проблемой при работе с устройствами и графиками, где количество открытых устройств нигде не сообщается. Для более общего случая вы можете использовать это:

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.

РЕДАКТИРОВАТЬ:sink выдает предупреждение, а не ошибку, поэтому я изменил код, чтобы он не работал вечно, к сожалению!

Чаще всего я сталкиваюсь с этим, когда возникает ошибка, препятствующая закрытию приемника. Например, следующее оставит открытый приемник после выполнения.

      sink("output.txt")
my_function_that_will_error()
sink()

Этого можно избежать, используя on.exit(sink()). Это закроет приемник «при выходе текущей функции (естественно или в результате ошибки)» (документация здесь ).

Но вы должны изменить порядок:

      sink("output.txt")
on.exit(sink())
my_function_that_might_error()

Итак, мы создаем приемник, говорим R закрыть его при выходе, а затем выполняем код, который может привести к ошибке. Это закроет приемник независимо от того, ошибки кода или нет.

Другие вопросы по тегам