【问题标题】:How to rethrow an error in R?如何重新抛出R中的错误?
【发布时间】:2014-01-13 05:47:41
【问题描述】:

我将使用tryCatch 捕获一个错误,并尝试处理该错误。但是,如果我无法在本地处理错误(即委托给调用堆栈中更高层的父函数的错误处理程序),我该如何重新抛出错误?

我尝试使用signalCondition,但没有看到重新抛出的错误,我看到的只是NULL

> error.can.be.handled <- function(e) F
> 
> foo <- function() stop("foo stop!")
> tryCatch(foo(),
+   error = function(e) {
+       if (error.can.be.handled(e)) {
+           # handle error
+       }
+       else
+           signalCondition(e) # Rethrow error
+   }
+ )
NULL  # I expected to see 'Error in foo() : foo stop!' here

怎么了?

【问题讨论】:

  • @Martin Morgan 有正确答案,但要添加更多细节,您的版本不起作用,因为stop 除了发出条件信号外,还会输出错误消息并中止执行通过调用中止重启。所以可见的“错误”实际上与默认错误处理程序没有任何关系,它只是stop 中的代码,这就是为什么你需要调用stop 来实现它并且信号条件还不够。有关详细信息,请参阅stop 来源。

标签: r error-handling try-catch


【解决方案1】:
tryCatch(stop("oops"), error=function(e) stop(e))

将重新发出停止条件的信号,尽管上下文已丢失

> tryCatch(stop("oops"), error=function(e) stop(e))
Error in doTryCatch(return(expr), name, parentenv, handler) : oops
> traceback()
5: stop(e)
4: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
2: tryCatchList(expr, classes, parentenv, handlers)
1: tryCatch(stop("oops"), error = function(e) stop(e))
> tryCatch(stop("oops"))
Error in tryCatchList(expr, classes, parentenv, handlers) : oops
> traceback()
3: stop("oops")
2: tryCatchList(expr, classes, parentenv, handlers)
1: tryCatch(stop("oops"))

按照@tonytonov 的建议,只返回e 确实表明已经发生了某种情况,但并不表示发生了错误。

【讨论】:

  • 如果您希望保留上下文,请使用withCallingHandlers 而不是tryCatch
【解决方案2】:

您可以使用一种解决方法来完全避免捕获并重新抛出错误。基本上,只有当相关代码失败时,才使用带有 on.exit 处理程序的成功标志来运行代码块:

foo <- function() stop("foo stop!")
runFoo <- function() {
    success <- FALSE
    on.exit({
        if (!success) {
            ## Handle failure
        }
    })
    result <- foo()
    success <- TRUE
    result
}
runFoo()

这种方法的主要缺点是,虽然您知道发生了错误(因为success 从未设置为 TRUE),但您无法访问错误对象本身,因此您需要使用其他方法检测您是否可以处理错误。

需要runFoo 包装函数,因为on.exit 表达式在退出当前函数时运行,因此需要在函数内部运行。如果您正在编写的代码已经在函数内部,那么您不需要使用这个包装器。

【讨论】:

    【解决方案3】:

    在 signalCondition() 中没有任何必要:

    tryCatch(foo(),
        error = function(e) {
            if (error.can.be.handled(e)) {
                # handle error
            }
            else
                e # Rethrow error
        }
      )
    
    <simpleError in foo(): foo stop!>
    

    【讨论】:

    • 谢谢,但这个例子只是返回错误对象e而不是抛出它。请注意,如果包装在另一个函数中,您的示例将静默运行,而重新抛出的错误仍会停止执行并打印 Error in foo() : foo stop!
    • 啊,对。马丁的回答是纠正这一点:stop(e) 实际上是在做这项工作。
    猜你喜欢
    • 2017-06-29
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2012-10-17
    • 2019-06-15
    • 1970-01-01
    • 2012-10-28
    相关资源
    最近更新 更多