为什么withCallingHandlers仍然停止执行?

eli*_*ner 5 error-handling r

似乎withCallingHandlers实际上并没有捕获错误tryCatch,脚本仍然停止执行.

将代码段与tryCatch打印"之前"和"之后"的位置进行比较:

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

使用相同的片段withCallingHandlers不会打印"之后"并停止执行:

f2 <- function() {
  cat("before tryCatch\n")
  withCallingHandlers({
      stop("this is an error!")
    },
    error = function(cond) {
      print(cond$message)
    }
  )
  cat("after tryCatch\n")
}
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

一些背景

我想用它withCallingHandlers来分析发生错误时的调用堆栈sys.calls().

Advanced R说,应该是可能的:

在处理程序withCallingHandlers()被称为在产生而在处理条件下的呼叫的上下文中tryCatch()被称为在的上下文中tryCatch().

Mar*_*gan 8

调用处理程序提供了一种在途中"触摸"条件的方法,可能在将信息记录到交互式会话中之前将错误记录到文件中.

如果调用处理程序实际上没有返回,则调用处理程序可用于"消除"警告,消息或错误.你可以让一个调用处理程序不使用restarts返回 - 包围你想要在调用中继续执行的代码withRestarts(),并在处理程序中调用restart:

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")
}
Run Code Online (Sandbox Code Playgroud)

更常见的是,重启在一个代码块中建立(如在内置函数中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>
Run Code Online (Sandbox Code Playgroud)