使用options(show.error.locations = TRUE)
处理异常时,使用tryCatch
显示错误位置似乎不起作用。我试图显示错误的位置,但我不知道如何:
options(show.error.locations = TRUE)
tryCatch({
some_function(...)
}, error = function (e, f, g) {
e <<- e
cat("ERROR: ", e$message, "\nin ")
print(e$call)
})
如果我查看变量e
,那么该位置似乎不存在:
> str(e)
List of 2
$ message: chr "missing value where TRUE/FALSE needed"
$ call : language if (index_smooth == "INDEX") { rescale <- 100/meanMSI[plotbaseyear] ...
- attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
如果我没有捕获错误,它将与源文件和行号一起打印在控制台上。如何使用tryCatch?
答案 0 :(得分:2)
<强>上下文强>
如Willem van Doesburg所述,无法使用traceback()
function来显示tryCatch()
发生错误的位置,据我所知,目前还没有实用的方法使用tryCatch 时,在R 中存储基本函数的错误位置。
单独错误处理程序的想法
我找到的可能解决方案由两部分组成,主要部分是编写一个类似于Chrispy from "printing stack trace and continuing after error occurs in R"的错误处理程序,它生成一个包含错误位置的日志。 第二部分是将此输出捕获到变量中,类似于Ben Bolker in "is it possible to redirect console output to a variable"建议的那样。
当出现错误然后处理时,R中的调用堆栈似乎被清除(我可能错了所以欢迎任何信息),因此我们需要在错误发生时捕获它。
有错误的脚本
我使用了前面一个问题中的一个示例,其中R error occured将以下函数存储在一个名为“TestError.R”的文件中,我在下面的示例中调用该文件:
# TestError.R
f2 <- function(x)
{
if (is.null(x)) "x is Null"
if (x==1) "foo"
}
f <- function(x)
{
f2(x)
}
# The following line will raise an error if executed
f(NULL)
错误跟踪功能
这是我在上面提到的Chrispy的代码中修改的功能。
执行时,如果出现错误,下面的代码将打印发生错误的位置,在上述功能的情况下,它将打印:
"Error occuring: Test.R#9: f2(x)"
和"Error occuring: Test.R#14: f(NULL)"
表示错误是由于第14行的f(NULL)
函数出现问题导致第9行引用f2()
函数
# Error tracing function
withErrorTracing = function(expr, silentSuccess=FALSE) {
hasFailed = FALSE
messages = list()
warnings = list()
errorTracer = function(obj) {
# Storing the call stack
calls = sys.calls()
calls = calls[1:length(calls)-1]
# Keeping the calls only
trace = limitedLabels(c(calls, attr(obj, "calls")))
# Printing the 2nd and 3rd traces that contain the line where the error occured
# This is the part you might want to edit to suit your needs
print(paste0("Error occuring: ", trace[length(trace):1][2:3]))
# Muffle any redundant output of the same message
optionalRestart = function(r) { res = findRestart(r); if (!is.null(res)) invokeRestart(res) }
optionalRestart("muffleMessage")
optionalRestart("muffleWarning")
}
vexpr = withCallingHandlers(withVisible(expr), error=errorTracer)
if (silentSuccess && !hasFailed) {
cat(paste(warnings, collapse=""))
}
if (vexpr$visible) vexpr$value else invisible(vexpr$value)
}
存储错误排名和消息
我们调用上面的脚本TestError.R
并在变量中捕获打印输出,此处称为errorStorage
,我们可以稍后处理或简单地显示。
errorStorage <- capture.output(tryCatch({
withErrorTracing({source("TestError.R")})
}, error = function(e){
e <<- e
cat("ERROR: ", e$message, "\nin ")
print(e$call)
}))
因此,我们将e
的值与呼叫和消息以及错误位置的位置保持一致。
errorStorage输出应如下所示:
[1] "[1] \"Error occuring: Test.R#9: f2(x)\" \"Error occuring: Test.R#14: f(NULL)\""
[2] "ERROR: argument is of length zero "
[3] "in if (x == 1) \"foo\""
希望这可能有所帮助。
答案 1 :(得分:0)
您可以在错误处理程序中使用traceback()来显示调用堆栈。 tryCatch中的错误不会产生行号。另请参阅回溯中的help。如果您以防御方式使用tryCatch语句,这将有助于缩小错误的位置。
这是一个有效的例子:
## Example of Showing line-number in Try Catch
# set this variable to "error", "warning" or empty ('') to see the different scenarios
case <- "error"
result <- "init value"
tryCatch({
if( case == "error") {
stop( simpleError("Whoops: error") )
}
if( case == "warning") {
stop( simpleWarning("Whoops: warning") )
}
result <- "My result"
},
warning = function (e) {
print(sprintf("caught Warning: %s", e))
traceback(1, max.lines = 1)
},
error = function(e) {
print(sprintf("caught Error: %s", e))
traceback(1, max.lines = 1)
},
finally = {
print(sprintf("And the result is: %s", result))
})