R - 自动创建每日文件以记录来自 RStudio 控制台的所有内容

R - Automatically create daily file to log everything from RStudio console

我通常为每个项目(每个项目持续几周)在一个 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()

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

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

这实现了我认为的效果,我说得对吗?有没有办法修改它(或做类似的事情),这将允许我也捕获输入和警告(基本上是控制台中看到的其余部分)?

谢谢!

预先说明:此答案不提供输入和消息。对你来说更强大的机制是使用R-markdown文档:它会捕获警告等,它会在错误时继续,它确实包括输入等。只需使用 RStudio 的 "knit document"(甚至笔记本),您将获得相同的效果。如果这不能满足您的需求并且您想坚持使用 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.

你不能同时下沉"output"和"messages",所以你需要调用sink两次,每种类型一次。 (它们完全分开处理,因此您也需要单独关闭它们。)

CAVEAT EMPTOR:help page 警告不要下沉消息:

 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")

好处是您将分别安全地收到这两种类型的消息。不好的是您将无法将特定的 error/warning 绑定到代码或输出中的任何位置。如果这不打扰你,坚持下去。

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

这种方法的问题是两个 "processes" 正在写入同一个文件,可能是同时写入。这可能会导致数据丢失或(更有可能)jumbled/interleaved 输出。我没有仔细研究代码以查看是否会发生这种情况,也没有对它进行详尽的测试。 您已收到警告。

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