接收器不会释放文件

I L*_*ode 28 r sink

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

sink('sink-closing.txt')
cat('Hello world!')
sink()
Run Code Online (Sandbox Code Playgroud)

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

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

假设我的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()
Run Code Online (Sandbox Code Playgroud)

接下来,我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
Run Code Online (Sandbox Code Playgroud)

现在,假设我正在调试R脚本并想要打印到控制台.我可以sink()多次打电话来关闭早期的接收器.如果我调用它3次,那么我最终可以像以前一样打印到控制台.但我如何知道需要关闭多少水槽?

Das*_*son 35

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

sink.reset <- function(){
    for(i in seq_len(sink.number())){
        sink(NULL)
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 阅读帮助文件中*所有*文档的另一个胜利!:-) (2认同)

42-*_*42- 34

closeAllConnections()   # .........................
Run Code Online (Sandbox Code Playgroud)

  • @Dason - 可能是因为`closeAllConnections`是一个非常粗糙的工具用于此目的,因为它将关闭任何其他打开的连接 - 而不仅仅是当前打开的'sinks'. (9认同)
  • ...现在为什么他们不会链接到那个或在接收器帮助文件中提到它? (6认同)
  • 他们没有完全掩盖这是一种连接的事实。并且有一个指向“连接”页面的链接。因此,它最终是指向`?showConnections`的两跳链接。 (2认同)

Sco*_*hie 9

根据@ mnel的评论:

sinkall <- function() {
  i <- sink.number()
  while (i > 0) {
    sink()
    i <- i - 1
  }
}
Run Code Online (Sandbox Code Playgroud)

应该关闭所有打开的水槽.

在处理设备和绘图时,您可能还会遇到此问题,其中未在任何地方报告打开设备的数量.对于更一般的情况,您可以使用此:

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.
Run Code Online (Sandbox Code Playgroud)

编辑: sink抛出警告而不是错误所以我修改了代码,以便它不会永远运行,哎呀!


Sim*_*.A. 6

完全避免问题

这个问题可以通过使用“on.exit”函数来避免:

sink("output.txt")
on.exit(sink())
my_function_that_might_error()
Run Code Online (Sandbox Code Playgroud)

解释

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

sink("output.txt")
my_function_that_will_error()
sink()
Run Code Online (Sandbox Code Playgroud)

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

但你必须改变顺序:

sink("output.txt")
on.exit(sink())
my_function_that_might_error()
Run Code Online (Sandbox Code Playgroud)

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


局限性

请注意,交互运行时, 的行为on.exit可能无法按预期工作。如果该行在on.exit(sink())控制台上运行,则会在所有当前命令结束时立即触发。

因此,这种方法需要获取脚本或在某些 R 函数/进程中创建和关闭接收器。

请参阅文档以on.exit获取更多信息。