【问题标题】:Sink does not release file接收器不释放文件
【发布时间】:2013-09-10 23:45:01
【问题描述】:

我知道sink() 函数可用于将 R 输出转移到文件中,例如

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

是否有一个简单的命令可以关闭所有未完成的接收器?

下面,我详细说明我的问题。

假设我的 R 脚本在 R 脚本中打开了一个 sink(),但在该脚本关闭 sink() 之前,R 脚本中出现了错误。我可能会多次运行 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-script 多次,说错了 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 次,那么我终于可以像以前一样打印到控制台了。但是我怎么知道我需要关闭多少个接收器?

【问题讨论】:

  • 你能用sink.number吗?

标签: r sink


【解决方案1】:
closeAllConnections()   # .........................

【讨论】:

  • ...现在他们为什么不在接收器帮助文件中链接或提及它?
  • 他们并没有完全隐藏它是一种连接的事实。还有一个指向connection 页面的链接。所以它最终成为?showConnections 的两跳链接。
  • @Dason -- 可能是因为closeAllConnections 是一个非常粗糙的工具用于此目的,因为它会关闭任何其他打开的连接——而不仅仅是当前打开的“接收器”。
  • @JoshO'Brien 这是一个很好的观点——但我认为至少在 sink 的文档中提到它不会有什么坏处。
  • 对我来说,这还有一个额外的好处,那就是通过在 Windows 上的 RevolutionR 中运行 foreach 循环来关闭生成的进程,而不是终止进程!双重打击,谢谢:-)
【解决方案2】:

您可以使用sink.number() 告诉您已经设置了多少转移,然后多次调用sink。把它放到一个函数中你可以有这个

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

【讨论】:

  • 阅读所有帮助文件中的文档的另一个胜利! :-)
【解决方案3】:

基于@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 抛出警告而不是错误,所以我修改了代码,让它不会永远运行,哎呀!

【讨论】:

    【解决方案4】:

    我遇到这种情况的最常见情况是发生错误,导致接收器无法关闭。例如,以下将在执行后留下一个打开的接收器。

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

    使用on.exit(sink()) 可以避免这种情况。这将在“当前函数退出(自然退出或由于错误)”(documentation here)时关闭接收器。

    但你必须改变顺序:

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

    所以我们创建了 sink,告诉 R 在它退出时关闭它,然后执行可能出错的代码。无论代码是否错误,这都会关闭接收器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 2016-03-02
      • 2013-10-21
      相关资源
      最近更新 更多