看来withCallingHandlers实际上并没有像tryCatch那样捕获错误,并且脚本仍然停止执行。

将代码段与tryCatch进行比较,其中同时打印了“before”和“after”:

f1 <- function() {
  cat("before tryCatch\n")
  tryCatch({
      stop("this is an error!")
    },
    error = function(cond) {
      print(cond$message)
    }
  )
  cat("after tryCatch\n")
}

使用与withCallingHandlers相同的代码段,该代码段不打印“之后”并停止执行:
f2 <- function() {
  cat("before tryCatch\n")
  withCallingHandlers({
      stop("this is an error!")
    },
    error = function(cond) {
      print(cond$message)
    }
  )
  cat("after tryCatch\n")
}

我究竟做错了什么?

一些上下文

我想使用withCallingHandlers在使用sys.calls()发生错误的时候分析调用堆栈。

根据Advanced R应该是可能的:

最佳答案

调用处理程序提供了一种“接触”整个过程的条件的方法,可以在向用户发出交互式 session 的信号之前将错误记录到文件中。

如果调用处理程序实际上没有返回,则可以使用调用处理程序来“消除”警告,消息或错误。您可以使调用处理程序不使用重新启动返回-将您想要继续执行的代码包含在对withRestarts()的调用中,然后在处理程序中调用重新启动:

f2 <- function() {
  cat("before tryCatch\n")
  withCallingHandlers({
      withRestarts({
          stop("this is an error!")
      }, muffleStop=function() {
          message("'stop' muffled")
      })
    },
    error = function(cond) {
      print(cond$message)
      invokeRestart("muffleStop")
    }
  )
  cat("after tryCatch\n")
}

通常,重新启动是在一个代码块中建立的(如内置函数warning),然后在一个完全独立的代码块中进行调用(如内置函数suppressWarnings:
> warning
function (..., call. = TRUE, immediate. = FALSE, noBreaks. = FALSE,
    domain = NULL)
{
        ##
        ## ...
        ##
        withRestarts({
            .Internal(.signalCondition(cond, message, call))
            .Internal(.dfltWarn(message, call))
        }, muffleWarning = function() NULL)
        ##
        ## ...
        ##
}
<bytecode: 0x51a4730>
<environment: namespace:base>
> suppressWarnings
function (expr)
{
    ops <- options(warn = -1)
    on.exit(options(ops))
    withCallingHandlers(expr,
        warning = function(w) invokeRestart("muffleWarning"))
}
<bytecode: 0x35c2a60>
<environment: namespace:base>

09-29 23:16