嵌套TryCatch的奇怪行为

时间:2015-10-21 09:50:56

标签: r try-catch

假设您有一个使用TryCatch的函数f:

f <- function() {
  tryCatch(stop('Argh'), error = function(x) {
      message('f() error handler')
      warning(x)
    })
  message('computing')
  "Very Important Result"
}

>res <- f()
# f() error handler
# computing
# Warning message:
# In doTryCatch(return(expr), name, parentenv, handler) : Argh

>identical(res, "Very Important Result")
# [1] TRUE
到目前为止一切顺利。

但现在:

tryCatch(x <- f(), error = function(x) {
  message('OUTER error handler !!!')
 })
# f() error handler
# OUTER error handler !!!

> x
Error: object 'x' not found

在这种情况下,计算从未达到表达式 f中的消息('计算') 问题:这是预期的吗?

1 个答案:

答案 0 :(得分:1)

try()是使用tryCatch()实现的,因此单凭这不能成为预期无法正常工作的原因。

try
#> function (expr, silent = FALSE) 
#> {
#>     tryCatch(expr, error = function(e) {
#>         call <- conditionCall(e)
#>         if (!is.null(call)) {
#>             if (identical(call[[1L]], quote(doTryCatch))) 
#>                 call <- sys.call(-4L)
#>             dcall <- deparse(call)[1L]
#>             prefix <- paste("Error in", dcall, ": ")
#>             LONG <- 75L
#>             msg <- conditionMessage(e)
#>             sm <- strsplit(msg, "\n")[[1L]]
#>             w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], 
#>                 type = "w")
#>             if (is.na(w)) 
#>                 w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], 
#>                   type = "b")
#>             if (w > LONG) 
#>                 prefix <- paste0(prefix, "\n  ")
#>         }
#>         else prefix <- "Error : "
#>         msg <- paste0(prefix, conditionMessage(e), "\n")
#>         .Internal(seterrmessage(msg[1L]))
#>         if (!silent && identical(getOption("show.error.messages"), 
#>             TRUE)) {
#>             cat(msg, file = stderr())
#>             .Internal(printDeferredWarnings())
#>         }
#>         invisible(structure(msg, class = "try-error", condition = e))
#>     })
#> }
#> <bytecode: 0xa4a390>
#> <environment: namespace:base>

原来问题不在于嵌套tryCatch(),而在于warning(x)。后者抛出一个错误(由'外部'tryCatch()捕获)。相应地更改示例会给我们预期的结果。

f <- function() {
  tryCatch(stop('Argh'), error = function(w) {
      message('f() error handler')
      warning(w$message)
    })
  message('computing')
  "Very Important Result"
}

tryCatch(x <- f(), error = function(e) str(e))
#> f() error handler
#> Warning in value[[3L]](cond): Argh
#> computing
x
#> [1] "Very Important Result"