如何为R实现"is.error()",以识别和解析错误?

Ite*_*tor 16 error-handling r

我试图测试对象是否是错误的结果.用例主要是通过一个foreach()产生错误的循环产生的(虽然,对于测试来说,似乎只能将simpleError()一个变量分配给一个变量),我很困惑如何确定何时发生这种情况:我怎么能测试一个实际上,给定对象是一个错误?一旦我确定这是一个错误,除了消息之外我还能提取什么?也许我错过了关于R的错误处理设施的一些东西,因为似乎有必要从头编写错误对象测试功能.

以下是两个示例,一个使用foreach,.errorhandling参数设置为pass.如果数据切片出现异常,我已经开始将其用作大规模或无人值守处理的默认设置.这样的异常是罕见的,并且不值得崩溃整个for循环(特别是如果异常发生在最后,这似乎是我的默认行为murphysListSortingAlgorithm();-)).相反,期望事后检测.

library(foreach)
library(doMC)
registerDoMC(2)
results = foreach(ix = 1:10, .errorhandling = "pass") %dopar%{
    if(ix == 6){
        stop("Perfect")
    } 
    if(ix == 7){
        stop("LuckyPrime")
    } else {
        return(ix)
    }
}
Run Code Online (Sandbox Code Playgroud)

为简单起见,这是一个非常简单的错误(根据定义):

a = simpleError("SNAFU")
Run Code Online (Sandbox Code Playgroud)

虽然似乎没有被这样的命令is.error(),像命令typeof()mode()似乎是毫无意义的,我已经找到了最好的方法是使用class()attributes(),这给那些指示错误的属性.如何以确保我有错误并完全处理该错误的方式使用这些?例如a$message返回SNAFU,但是a$callNULL.我应该期望从中提取任何有用的东西res[[6]]$call吗?


注1:如果一个人没有多核功能来重现第一个例子,我应该指出它results[[6]]不同于simpleError("Perfect"):

> b = simpleError("Perfect")
> identical(results[[6]], b)
[1] FALSE
> results[[6]]
<simpleError in eval(expr, envir, enclos): Perfect>
> b
<simpleError: Perfect>
Run Code Online (Sandbox Code Playgroud)

这说明了为什么我不能(非常天真)测试list元素是否为vanilla simpleError.

注2.我知道try并且tryCatch在某些情况下使用它们.但是,我不完全确定如何使用它们来后处理一个foreach循环的输出.例如,results第一个例子中的对象:我觉得用tryCatch包装器处理它的元素是不合理的.对于操作的RHS,即foreach()循环,我不确定是否tryCatch会按照我的意图行事.我可以使用它来捕获错误,但我想我需要获取消息并在此处插入处理.我看到两个问题:每个循环都需要包含一个tryCatch(),否定部分.errorhandling参数,我仍然无法在以后对该results对象进行后处理.如果这是进行此处理的唯一方法,那么它就是解决方案,但这意味着无法以与许多其他R对象类似的方式识别和处理错误,例如矩阵,向量,数据帧等.


更新1.我在foreach循环中添加了一个额外的停止触发器,以便识别和解析两个不同的消息,以防这有用.

更新2.我选择Richie Cotton的答案.它似乎是我应该寻找的最完整的解释,尽管完整的实现需要其他几个代码(以及最新版本的R).最重要的是,他指出我们需要牢记两种类型的错误,这对于彻底解决尤为重要.另请参阅其他人的评论和答案,以便充分开发自己的is.error()测试功能; 在查找结果列表中的错误时,我给出的答案可能是一个有用的开始,而Richie的代码是测试函数的一个很好的起点.

Ric*_*ton 8

你可能会在野外看到的两种类型的错误simpleError就像你到达这里一样,而try-errors是在调用中包含一些异常抛出代码的结果try.有人可能会创建自己的错误类,尽管这些很少见,应该基于这两个类中的一个.事实上(自R2.14.0起)try-errors包含simpleError:

e <- try(stop("throwing a try-error"))
attr(e, "condition")
Run Code Online (Sandbox Code Playgroud)

检测a simpleError是直截了当的.

is_simple_error <- function(x) inherits(x, "simpleError")
Run Code Online (Sandbox Code Playgroud)

try catch错误的等价物是

is_try_error <- function(x) inherits(x, "try-error")
Run Code Online (Sandbox Code Playgroud)

所以在这里,您可以通过将结果应用于结果列表来检查问题的结果.

the_fails <- sapply(results, is_simple_error)
Run Code Online (Sandbox Code Playgroud)

同样,返回消息和呼叫是一行的.为方便起见,我已将调用转换为字符串,但您可能不希望这样.

get_simple_error_message <- function(e) e$message
get_simple_error_call <- function(e) deparse(e$call)

sapply(results[the_fails], get_simple_error_message)
sapply(results[the_fails], get_simple_error_call)
Run Code Online (Sandbox Code Playgroud)