我在服务器上运行的 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...
})
运行上面的代码会产生以下输出:
simpleError in f(): object 'variable.not.found' not found
No traceback available
回溯不可用,原因记录在 R 帮助 (
?traceback
) 中:Errors which are caught via try or tryCatch do not generate a traceback, so what is printed is the call sequence for the last uncaught error, and not necessarily for the last error.
换句话说:用
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)
时,R 会跟踪源代码引用.您可以将此选项添加到您的 .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
tryCatchLog
function而不是使用完整的包装。示例(演示)
见 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
关于R:在记录堆栈跟踪后捕获错误并继续执行(tryCatch 没有可用的回溯),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39964040/