假设我在脚本中有一堆R代码,并且我想将从.GlobalEnv运行的所有R代码与错误和警告消息一起记录到平面文件或数据库中。
我可以编写一个简单的logme函数,如下所示,或者通过更改options(error = mylogginfunction)
mylogfile <- tempfile()
logme <- function(x){
mode <- "at"
if(!file.exists(mylogfile)){
mode <- "wt"
}
myconn <- file(mylogfile, mode)
writeLines(x, myconn)
close(myconn)
invisible()
}
logme(sprintf("%s: started some yadayada, ", Sys.time()))
x <- 10
x * 7
logme(sprintf("%s: done with yadayada", Sys.time()))
## Get the log
cat(readLines(mylogfile))
日志打印出来: 2015-05-14 17:24:31:开始一些yadayada,2015-05-14 17:24:31:用yadayada完成
但我想要的是,日志文件记下了执行的表达式,而不必在每个语句周围编写包装器。 我希望日志看起来像。 2015-05-14 17:24:31:开始一些yadayada, x&lt; - 10,x * 7 2015-05-14 17:24: 31:完成yadayada
所以我的问题是,如何获取R正在执行的内容,以便我可以将执行的表达式存储在日志/数据库中。而且无需在每个表达式之前编写函数调用(如myhandler(x < - 10); myhandler(x * 10))。 对此有何帮助?
答案 0 :(得分:4)
要捕获输入命令,您可以使用addTaskCallback
mylogfile <- tempfile()
addTaskCallback(
function(...) {
expr <- deparse(as.expression(...)[[1]]) # it could handled better...
cat(expr, file=mylogfile, append=TRUE, sep="\n")
# or cat(sprintf("[%s] %s", Sys.time(), expr),...) if you want timestamps
TRUE
}
,name="logger"
)
x <- 10
x * 7
removeTaskCallback("logger")
然后结果是:
cat(readLines(mylogfile), sep="\n")
... addTaskCallback definition ...
x <- 10
x * 7
但你得到的是解析表达式,这意味着行
x+1;b<-7;b==2
将记录为
x + 1
b <- 7
b == 2
另外:
message
或warning
error
日志记录不会被触发,那么你需要单独的函数来处理它答案 1 :(得分:0)
这可能在每种情况下都很简单,但你可以试试这个:
将myhandler定义为:
myhandler <- function(x, file = stdout()) {
expr <- substitute(x)
for(e_line in as.list(expr)) {
cat( file = file, as.character(Sys.time()), capture.output(e_line), "\n")
eval(e_line, envir = parent.frame())
}
}
将它与括号内的代码一起使用:
myhandler({
a <- 1
a <- a + 1
print(a)
})
结果:
# 2015-05-14 18:46:34 `{`
# 2015-05-14 18:46:34 a <- 1
# 2015-05-14 18:46:34 a <- a + 1
# 2015-05-14 18:46:34 print(a)
# [1] 2
答案 2 :(得分:0)
我承认,我并没有真正得到什么&#34;让运行的表达式在与R命令运行的相同过程中可用#34;意味着我们在评论中聊了一下。但是,我扩展了我的想法。您可以使用以下行创建logGenerator.R
文件:
logGenerator<-function(sourcefile,log) {
..zz <- file(log, open = "at")
sink(..zz)
sink(..zz, type = "message")
on.exit({
sink(type="message")
sink()
close(..zz)
})
..x<-parse(sourcefile)
for (..i in 1:length(..x)) {
cat(as.character(Sys.time()),"\n")
cat(as.character(..x[..i]),"\n")
..y<-eval(..x[..i])
}
}
此函数将源文件和日志文件名作为参数。该脚本将采用R文件并记录每条指令的执行时间。然后它将表达式记录在同一个日志文件中。定向到stdout()
的每个输出和错误消息都定向到日志文件。您显然不必以任何方式修改源文件。