【问题标题】:Repeating values in loop until error disappears在循环中重复值直到错误消失
【发布时间】:2017-11-13 03:49:47
【问题描述】:

我目前正在使用 for 循环使用 Googleway 包对大量地址进行地理编码。最初,我遇到了“500 个内部服务器错误”停止执行循环的问题。我能够使用 tryCatch() 解决这个问题。但是,由于这往往是一个暂时性错误,我希望该函数重复引发错误的地址,直到它收到结果或达到任意次数的尝试,比如 10 次。

不幸的是,我发现 tryCatch() 和与之相关的文档令人困惑,所以除了让它抛出错误消息并继续前进之外,我不知道如何做任何事情。这是我当前的代码:

rugeocoder.fun <- function(addr){
              require(googleway)
              output <- vector("list", length=length(addr))
              tryCatch({
                for(i in 1:length(addr)){
                  output[[i]] <- google_geocode(address=addr[i], key="myapikey", language="ru", simplify=T)
                  print(i)

                }},error=function(e) output[[i]] <- "Error: reattempt")
              return(output)
              }

【问题讨论】:

    标签: r loops error-handling try-catch


    【解决方案1】:

    您可能希望分离出安全调用google_geocode() 和循环地址的逻辑。

    这是一个修改其他函数以重复调用它们直到它们工作的函数,或者它们失败max_attempts 次。修饰其他函数的函数有时称为“副词”。

    safely <- function(fn, ..., max_attempts = 5) {
      function(...) {
        this_env <- environment()
        for(i in seq_len(max_attempts)) {
          ok <- tryCatch({
              assign("result", fn(...), envir = this_env)
              TRUE
            },
            error = function(e) {
              FALSE
            }
          )
          if(ok) {
            return(this_env$result)
          }
        }
        msg <- sprintf(
          "%s failed after %d tries; returning NULL.",
          deparse(match.call()),
          max_attempts
        )
        warning(msg)
        NULL
      }
    }
    

    试试这个生成随机数的简单函数,如果太小会抛出错误。

    random <- function(lo, hi) {
      y <- runif(1, lo, hi)
      if(y < 0.75) {
        stop("y is less than 0.75")
      }
      y
    }
    safe_random <- safely(random)
    safe_random() # will sometimes work, will sometimes return NULL
    safe_random(0, 10) # will usually work
    

    在你的情况下,你想修改 google_geocode() 函数。

    safe_google_geocode <- safely(google_geocode)
    

    然后遍历调用这个的地址。

    geocodes <- lapply( # purrr::map() is an alternative
      addresses,
      safe_google_geocode,
      key = "myapikey", 
      language = "ru", 
      simplify = TRUE
    )
    

    【讨论】:

    • 您介意澄清一下您为什么使用this_env &lt;- environment() 吗?这里的环境有点复杂,我无法理解结果如何从 safe() 函数创建的闭包移动到全局环境以便分配给对象。
    • @SeanNorton 是的,这令人困惑。 tryCatch() 好像使用了自己的环境,所以只做result &lt;- fn(...) 是不行的。
    • 我认为 @SeanNorton this_env 是属于 safe_whatever() 闭包的环境。
    • 嗯,不幸的是,assign() 似乎无法正常工作 - 每次迭代我都会收到错误 In assign("result", fn(...), envir = this_env) : restarting interrupted promise evaluation,返回一个完全为空的元素列表。关于如何解决这个问题的任何想法?
    • @SeanNorton 嗯。我不确定问题出在哪里。用eval.parent() 评估fn(...) 有帮助吗? stackoverflow.com/q/20596902/134830
    猜你喜欢
    • 2022-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-23
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    相关资源
    最近更新 更多