我在服务器上运行的 R 中有许多无人值守的批处理作业,我必须在它们运行后分析作业失败。
我正在 try catch 错误以记录它们并从错误中优雅地恢复,但我无法获得堆栈跟踪 (traceback
) 来记录导致错误的 R 命令的代码文件名和行号。一个(愚蠢的)可重现的例子:
f <- function() {
1 + variable.not.found # stupid error
}
tryCatch( f(), error=function(e) {
# Here I would log the error message and stack trace (traceback)
print(e) # error message is no problem
traceback() # stack trace does NOT work
# Here I would handle the error and recover...
})
运行上面的代码会产生以下输出:
回溯不可用,原因记录在 R 帮助 (
?traceback
) 中:换句话说:使用
tryCatch
捕获错误确实会终止堆栈跟踪!我怎样才能
多谢!
最佳答案
抱歉回答太长,但我想在一个答案中总结所有知识和引用!
需要解决的主要问题
tryCatch
将调用堆栈“展开”到 tryCatch
调用,以便 traceback
和 sys.calls
不再包含完整的堆栈跟踪,以识别导致错误或警告的源代码行。 tryCatch
aborts the execution if you catch a warning 通过为 warning
条件传递处理函数。如果您只想记录警告,则无法正常继续执行。 dump.frames
写入堆栈跟踪的评估环境(帧)以允许事后调试(= 检查每个函数调用中可见的变量值),但 dump.frames
"forgets" to save the workspace too if you set the parameter to.file = TRUE
。因此可能会丢失重要的对象。 解决方案概念
withCallingHandlers
而不是 tryCatch
来获取指向引发错误或警告的源代码行的完整堆栈跟踪。 withCallingHandlers
中(不在 tryCatch
中)捕获警告,因为它仅调用处理程序函数但不更改程序流程。 withCallingHandlers
环绕 tryCatch
以根据需要捕获和处理错误。 dump.frames
和参数 to.file = FALSE
将转储写入名为 last.dump
的全局变量,并通过调用 save.image
将其与全局环境一起保存到文件中。 futile.logger
包。 options(keep.source = TRUE)
时跟踪源代码引用。您可以将此选项添加到您的 .Rprofile
文件中,或使用设置此选项的启动 R 脚本,然后 source
您的实际 R 脚本。 limitedLabels
。 执行
代码模板
您应该使用以下代码片段,而不是使用
tryCatch
:library(futile.logger)
tryCatch(
withCallingHandlers(<expression>,
error = function(e) {
call.stack <- sys.calls() # is like a traceback within "withCallingHandlers"
dump.frames()
save.image(file = "last.dump.rda")
flog.error(paste(e$message, limitedLabels(call.stack), sep = "\n"))
}
warning = <similar to error above>
}
error = <catch errors and recover as you would do it normally>
# warning = <...> # never do this here since it stops the normal execution like an error!
finally = <your clean-up code goes here>
}
通过包 (
tryCatchLog
) 实现可重用我已经用上面提到的所有概念实现了一个简单的包。
它使用
tryCatchLog
包提供了一个函数 futile.logger
。用法:
library(tryCatchLog) # or source("R/tryCatchLog.R")
tryCatchLog(<expression>,
error = function(e) {
<your error handler>
})
您可以在 github 上找到免费的源代码:
https://github.com/aryoda/tryCatchLog
您还可以对
source
function 进行 tryCatchLog
,而不是使用完整的软件包。示例(演示)
查看 demo file 提供了很多注释来解释它是如何工作的。
引用
其他
tryCatch
替换Handling errors before warnings in tryCatch
withJavaLogging
函数与其他包没有任何依赖关系,这也使用 limitedLabels
丰富了对调用堆栈的源代码引用:Printing stack trace and continuing after error occurs in R
其他有用的链接
http://adv-r.had.co.nz/Exceptions-Debugging.html
A Warning About warning() - avoid R's warning feature
In R, why does withCallingHandlers still stops execution?
How to continue function when error is thrown in withCallingHandlers in R
Can you make R print more detailed error messages?
How can I access the name of the function generating an error or warning?
How do I save warnings and errors as output from a function?
options(error=dump.frames) vs. options(error=utils::recover)
General suggestions for debugging in R
Suppress warnings using tryCatch in R
R Logging display name of the script
Background information about the "srcrefs" attribute (Duncan Murdoch)
get stack trace on tryCatch'ed error in R