尝试记录所有错误和警告futile.logger.
对于处理错误有点满意:
library(futile.logger)
options(error = function() { flog.error(geterrmessage()) ; traceback() ; stop() })
log("a")
# Error in log("a") : argument non numérique pour une fonction mathématique
# ERROR [2016-12-01 21:12:07] Error in log("a") : argument non numérique pour une fonction mathématique
#
# No traceback available
# Erreur pendant l'emballage (wrapup) :
Run Code Online (Sandbox Code Playgroud)
有冗余,但我可以很容易地之间的分离stderr,stdout以及日志文件,所以它不是一个问题.它肯定不漂亮,有一个额外的"总结"错误消息,不知何故由stop()我不理解的决赛造成,所以我愿意接受建议.
我找不到类似的警告解决方案.我尝试了什么:
options(warn = 1L)
options(warning.expression = expression(flog.warn(last.warning)))
log(- 1)
# [1] NaN
Run Code Online (Sandbox Code Playgroud)
但无济于事.
后续问题:我是否在不知不觉中忽略了最佳做法?
怎么样:
options(warning.expression =
quote({
if(exists("last.warning",baseenv()) && !is.null(last.warning)){
txt = paste0(names(last.warning),collapse=" ")
try(suppressWarnings(flog.warn(txt)))
cat("Warning message:\n",txt,'\n',sep = "")
}
}))
Run Code Online (Sandbox Code Playgroud)
In可以提供两个选项来记录R条件,如警告futile.logger和捕获所有警告,无论函数调用堆栈有多深:
withCallingHandlers为基本解决方案为了解释解决方案,我创建了一个产生警告和错误的简单R脚本:
# Store this using the file name "your_code_file.R"
# This could be your code...
f1 <- function(value) {
print("f1() called")
f2(value) # call another function to show what happens
print("f1() returns")
}
f2 <- function(value) {
print("f2() called")
a <- log(-1) # This throws a warning: "NaNs produced"
print(paste("log(-1) =", a))
b <- log(value) # This throws an error if you pass a string as value
print("f2() returns")
}
f1(1) # produces a warning
f1("not a number") # produces a warning and an error
Run Code Online (Sandbox Code Playgroud)
执行"按原样"(不记录)此代码生成此输出:
[1] "f1() called"
[1] "f2() called"
[1] "log(-1) = NaN"
[1] "f2() returns"
[1] "f1() returns"
[1] "f1() called"
[1] "f2() called"
[1] "log(-1) = NaN"
Error in log(value) : non-numeric argument to mathematical function
Calls: source -> withVisible -> eval -> eval -> f1 -> f2
In addition: Warning messages:
1: In log(-1) : NaNs produced
2: In log(-1) : NaNs produced
Run Code Online (Sandbox Code Playgroud)
withCallingHandlers)创建一个由R调用的新R文件,并提供未更改的(!)原始R脚本:
# Store this using the file name "logging_injector_withCallingHandlers.R"
# Main function to inject logging of warnings without changing your original source code
library(futile.logger)
flog.threshold(INFO)
# Injecting the logging of errors and warnings:
tryCatch(withCallingHandlers({
source("your_code_file.R") # call your unchanged code by sourcing it!
}, error = function(e) {
call.stack <- sys.calls() # "sys.calls" within "withCallingHandlers" is like a traceback!
log.message <- e$message
flog.error(log.message) # let's ignore the call.stack for now since it blows-up the output
}, warning = function(w) {
call.stack <- sys.calls() # "sys.calls" within "withCallingHandlers" is like a traceback!
log.message <- w$message
flog.warn(log.message) # let's ignore the call.stack for now since it blows-up the output
invokeRestart("muffleWarning") # avoid warnings to "bubble up" to being printed at the end by the R runtime
})
, error = function(e) {
flog.info("Logging injector: The called user code had errors...")
})
Run Code Online (Sandbox Code Playgroud)
如果执行此包装器代码,则R输出为:
$ Rscript logging_injector_withCallingHandlers.R
NULL
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 22:35:53] NaNs produced
[1] "log(-1) = NaN"
[1] "f2() returns"
[1] "f1() returns"
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 22:35:53] NaNs produced
[1] "log(-1) = NaN"
ERROR [2017-06-08 22:35:53] non-numeric argument to mathematical function
INFO [2017-06-08 22:35:53] Logging injector: The called user code had errors...
Run Code Online (Sandbox Code Playgroud)
如你看到的
参考文献:https://stackoverflow.com/a/19446931/4468078
tryCatchLog(我是作者)解决方案1有一些缺点,主要是:
我没有一次又一次地复制和粘贴上面的代码片段,而是开发了一个包,将上述withCallingHandlers逻辑封装在一个函数中,并添加其他功能,如
使用tryCatchLog创建包装文件来包装上面的R脚本文件
# Store this using the file name "logging_injector_tryCatchLog.R"
# Main function to inject logging of warnings without changing your original source code
# install.packages("devtools")
# library(devtools)
# install_github("aryoda/tryCatchLog")
library(tryCatchLog)
library(futile.logger)
flog.threshold(INFO)
tryCatchLog({
source("your_code_file.R") # call your unchanged code by sourcing it!
#, dump.errors.to.file = TRUE # Saves a dump of the workspace and the call stack named dump_<YYYYMMDD_HHMMSS>.rda
})
Run Code Online (Sandbox Code Playgroud)
并执行它Rscript来获得此(缩短!)结果:
# $ Rscript -e "options(keep.source = TRUE); source('logging_injector_tryCatchLog.R')" > log.txt
[1] "f1() called"
[1] "f2() called"
WARN [2017-06-08 23:13:31] NaNs produced
Compact call stack:
1 source("logging_injector_tryCatchLog.R")
2 logging_injector_tryCatchLog.R#12: tryCatchLog({
3 logging_injector_tryCatchLog.R#13: source("your_code_file.R")
4 your_code_file.R#18: f1(1)
5 your_code_file.R#6: f2(value)
6 your_code_file.R#12: .signalSimpleWarning("NaNs produced", quote(log(-1)))
Full call stack:
1 source("logging_injector_tryCatchLog.R")
2 withVisible(eval(ei, envir))
...
<a lot of logging output omitted here...>
Run Code Online (Sandbox Code Playgroud)
正如您在调用堆栈级别6清楚地看到的那样,源代码文件名和行号(#12)被记录为警告源以及抛出警告的源代码片段:
6 your_code_file.R#12 .signalSimpleWarning("NaNs产生",引用(log(-1)))