3

我通常为每个项目使用一个 script.R 文件(每个项目持续几周)。我想设置一个流程,这样每天当我打开 RStudio 时,我都可以启动一个文件,将我在控制台中看到的所有内容(输入、输出、警告)存储到一个文件中。我还希望它每天都创建一个新文件。我在这里阅读了一些关于如何做部分内容的讨论,但我不够聪明,无法自己将它们整合在一起。这是我到目前为止所拥有的:

sink(paste("filename.txt", strtrim(Sys.time(),10)), append=T, split=T)
x <- 1:5
y <- 2:6
z <- c(5, 8, 3, 5, 9)
reg <- lm(y ~ x)  #intentional "mistake" used to produce a warning
reg <- lm(z ~ x)
summary(reg)
sink()

我认为这完成了什么:如果这是我第一次这样做,我会得到一个日志文件,它会在一个新文件中捕获所有输出,但如果我在 AM 中做一些工作,它将添加到现有文件中,全部关闭出去,并在当天晚些时候重新开始。

这没有完成:它不捕获输入或警告消息,而且我认为它有点笨拙。

我是否正确,这完成了我认为的事情?有没有办法修改这个(或做类似的事情),让我也可以捕获输入和警告(基本上是控制台中看到的其余内容)?

谢谢!

4

1 回答 1

5

预先:这个答案不提供输入和消息。对您来说更强大的机制是使用 R-markdown 文档:它将捕获警告等,它将继续出错,它确实包含输入等。只需使用 RStudio 的“编织文档”(甚至笔记本),并且你会得到同样的效果。如果这不能满足您并且您想坚持下去sink,请继续阅读。

有一个参数sink允许保存警告和错误:

sink(file = NULL, append = FALSE, type = c("output", "message"),
     split = FALSE)
...
type: character string.  Either the output stream or the messages
      stream.  The name will be partially matched so can be
      abbreviated.

您不能同时接收“输出”和“消息”,因此您需要调用sink两次,每种类型调用一次。(它们完全分开处理,因此您也需要单独关闭它们。)

CAVEAT EMPTOR:帮助页面警告下沉消息:

 Sink-ing the messages stream should be done only with great care.
 For that stream 'file' must be an already open connection, and
 there is no stack of connections.

此外,它不支持split,因此您不会看到任何警告或错误。(这是一个足以阻止我使用它的重要问题......我只是突出显示整个控制台并保存在文本编辑器中。但我知道你正在尝试自动化事情,所以我们将继续.)

有两种方法可以做到这一点:安全(失去输出和消息之间的同步),以及未经充分测试的可能不安全。

安全地

msgcon <- file("out1-msg.txt", open = "a")
sink("out1.txt", type = "output", append = TRUE, split = TRUE)
sink(msgcon, type = "message") # does not support split
# do your work here
a <- 1
a
stop("huh?")
sink(NULL, type = "message")
sink(NULL, type = "output")

好处是您将分别且安全地收到这两种类型的消息。不好的是,您将无法将特定错误/警告与代码或输出中的任何位置联系起来。如果那不打扰您,请坚持下去。

未经过充分测试的可能不安全

这种方法的问题是两个“进程”可能同时写入同一个文件。这可能会导致数据丢失或(更有可能)输出混乱/交错。我还没有在代码中进行足够的修改以查看是否会发生这种情况,也没有对它进行详尽的测试。你已经被警告过了。

con <- file("out1.txt", open = "a") # use for both sinks
sink(con, type = "output", append = TRUE, split = TRUE)
sink(con, type = "message")
a <- 2
a
stop("uh-wha?")
sink(NULL, type = "message")
sink(NULL, type = "output")

您仍然需要type独立打开和关闭两个 s。

于 2017-08-31T19:05:43.727 回答