使用try Catch跳转到错误循环的下一个值?

时间:2011-11-11 12:20:58

标签: r error-handling exception-handling try-catch

我已经阅读了一些关于tryCatch和cuzzins的其他SO问题,以及文档:

但我仍然不明白。

我正在运行循环,如果发生以下任何一种错误,我想跳到next

for (i in 1:39487) {

  # EXCEPTION HANDLING
  this.could.go.wrong <- tryCatch(
                           attemptsomething(),
                           error=function(e) next
                         )
  so.could.this <- tryCatch(
                     doesthisfail(),
                     error=function(e) next
                   )

  catch.all.errors <- function() { this.could.go.wrong; so.could.this; }
  catch.all.errors;


  #REAL WORK
  useful(i); fun(i); good(i);

  }  #end for

(顺便说一下,我找不到next的文档)

当我运行时,R鸣喇叭:

Error in value[[3L]](cond) : no loop for break/next, jumping to top level

我在这里错过了什么基本观点? tryCatch显然属于for循环,为什么R不知道呢?

5 个答案:

答案 0 :(得分:73)

使用tryCatch的关键是意识到它返回一个对象。如果tryCatch内有错误,则此对象将继承自类error。您可以使用函数inherit来测试类继承。

x <- tryCatch(stop("Error"), error = function(e) e)
class(x)
"simpleError" "error"       "condition"  

修改:

参数error = function(e) e的含义是什么?这让我感到困惑,我认为在文档中没有很好地解释它。会发生什么是该参数捕获源自您tryCatch的表达式的任何错误消息。如果捕获到错误,则会返回tryCatch的值。在帮助文档中,这被描述为calling handlere内的参数error=function(e)是源自您代码的错误消息。


我来自程序式编程的旧学校,使用next是一件坏事。所以我会像这样重写你的代码。 (请注意,我删除了next中的tryCatch语句。):

for (i in 1:39487) {
  #ERROR HANDLING
  possibleError <- tryCatch(
      thing(),
      error=function(e) e
  )

  if(!inherits(possibleError, "error")){
    #REAL WORK
    useful(i); fun(i); good(i);
  }

}  #end for

函数next记录在? for。。

如果您想使用它而不是在if中使用主要工作例程,那么您的代码应如下所示:

for (i in 1:39487) {
  #ERROR HANDLING
  possibleError <- tryCatch(
      thing(),
      error=function(e) e
  )

  if(inherits(possibleError, "error")) next

  #REAL WORK
  useful(i); fun(i); good(i);

}  #end for

答案 1 :(得分:5)

rm(list=ls())
for (i in -3:3) {
  #ERROR HANDLING
  possibleError <- tryCatch({
    print(paste("Start Loop ", i ,sep=""))
    if(i==0){
      stop()
    }
  }
    ,
    error=function(e) {
      e
      print(paste("Oops! --> Error in Loop ",i,sep = ""))
    }
  )

  if(inherits(possibleError, "error")) next

  print(paste("  End Loop ",i,sep = ""))

}

答案 2 :(得分:4)

我在这里可以找到唯一真正详细的解释:http://mazamascience.com/WorkingWithData/?p=912

以下是该博客帖子中的代码片段,其中显示了tryCatch的工作原理

#!/usr/bin/env Rscript
# tryCatch.r -- experiments with tryCatch

# Get any arguments
arguments <- commandArgs(trailingOnly=TRUE)
a <- arguments[1]

# Define a division function that can issue warnings and errors
myDivide <- function(d, a) {
  if (a == 'warning') {
    return_value <- 'myDivide warning result'
    warning("myDivide warning message")
  } else if (a == 'error') {
    return_value <- 'myDivide error result'
    stop("myDivide error message")
  } else {
    return_value = d / as.numeric(a)
  }
  return(return_value)
}

# Evalute the desired series of expressions inside of tryCatch
result <- tryCatch({

  b <- 2
  c <- b^2
  d <- c+2
  if (a == 'suppress-warnings') {
    e <- suppressWarnings(myDivide(d,a))
  } else {
    e <- myDivide(d,a) # 6/a
  }
  f <- e + 100

}, warning = function(war) {

  # warning handler picks up where error was generated
  print(paste("MY_WARNING:  ",war))
  b <- "changing 'b' inside the warning handler has no effect"
  e <- myDivide(d,0.1) # =60
  f <- e + 100
  return(f)

}, error = function(err) {

  # warning handler picks up where error was generated
  print(paste("MY_ERROR:  ",err))
  b <- "changing 'b' inside the error handler has no effect"
  e <- myDivide(d,0.01) # =600
  f <- e + 100
  return(f)

}, finally = {

  print(paste("a =",a))
  print(paste("b =",b))
  print(paste("c =",c))
  print(paste("d =",d))
  # NOTE:  Finally is evaluated in the context of of the inital
  # NOTE:  tryCatch block and 'e' will not exist if a warning
  # NOTE:  or error occurred.
  #print(paste("e =",e))

}) # END tryCatch

print(paste("result =",result))

答案 3 :(得分:3)

我遗漏的一件事breaking out of for loop when running a function inside a for loop in R明确指出:

  • next在函数内部无效。
  • 您需要从函数内部(在我的情况下为Voldemort = TRUE)向外部发送一些信号或标记(例如tryCatch)。
  • (这就像修改本地私有函数中的全局公共变量一样)
  • 然后在函数外部,检查标志是否被挥动(Voldemort == TRUE)。如果是这样,请在函数外部调用breaknext

答案 4 :(得分:1)

我发现其他答案非常令人困惑。对于任何想在发生错误时跳到下一个循环迭代的人来说,这都是一个非常简单的实现

for (i in 1:10) {

  tryCatch(print(b), error = function(e) { print("hi"); skip_to_next <<- TRUE})

  if(skip_to_next) { next }     
}