如何在foreach循环R中处理API错误?

时间:2019-03-15 11:18:34

标签: r foreach error-handling parallel-processing

仅供参考,根据一些评论,我添加了更多信息。

我创建了以下函数来调用API:

keyword_checker <- function(keyword, domain, loc, lang){

  keyword_to_check <- as.character(keyword)

  api_request <- paste("https://script.google.com/blabalbalba",
                       "?kw=",keyword,
                       "&domain=",domain,
                       "&loc=",loc,
                       "&lang=",lang,sep="")
  api_request <- URLencode(api_request, repeated = TRUE)  
  source <-fromJSON(file = api_request)#Json file into Data Frame
  return(data.frame(do.call("rbind", source$data$result))) ##in order to extract only the "results" data

我正在将R软件包foreach()%dopar%doSNOW一起使用,以进行许多API调用(超过12万次调用)。 不幸的是,碰巧有一些errors(通常是超时连接),因此它使脚本停止。为了避免此问题,我使用了.errorhandling = 'pass'。现在,脚本不会停止,但是我想知道在得到答案之前是否有办法进行API调用?

这是我的剧本:

cl <- makeCluster(9)
registerDoSNOW(cl)

final_urls_checker <- foreach(i = 1:length(mes_urls_to_check), .combine=rbind, .errorhandling = 'pass', .packages='rjson') %dopar% {
  test_keyword <- as.character(mes_urls_to_check[i])
  results <- indexed_url(test_keyword)}  ##name of my function

##Stop cluster
stopCluster(cl)

我基本上希望我的脚本继续运行(不停止整个过程),直到我从API调用中得到答案为止

我是否需要在TryCatch中加入foreach函数,还是最好通过添加类似“如果API没有给出答案”之类的东西来“升级”我创建的函数呢? ,然后等到它得到?”

我希望这更清楚。

2 个答案:

答案 0 :(得分:2)

尝试在tryCatch函数内部使用foreach捕获预期的错误消息(此处由于超时导致API调用失败)。根据我的理解,以下是给定功能keyword_checker的示例代码片段。

library(foreach)
 cl <- makeCluster(9)
registerDoSNOW(cl)

final_urls_checker <- foreach(i = 1:length(mes_urls_to_check), .combine=rbind, .errorhandling = 'pass', 
    .packages='rjson') %dopar% {
  test_keyword <- as.character(mes_urls_to_check[i])
  #results <- keyword_checker(test_keyword)}  ##name of my function
  results <- function(test_keyword){
    dmy <- tryCatch(
    {
        keyword_checker(test_keyword)
    },
    error = function(cond){
        message = "Timeout error! Calling again..."
        dmy2 <- keyword_checker(test_keyword)
        return(dmy2) 
    }
    warning = function(cond){
        message("Warning message:")
        message(cond)
        return(NULL)
    }
    finally = {
        message(paste("Succesfully called API ", test_keyword))
    }
        )
    return(dmy)
  }

##Stop cluster
stopCluster(cl)

这里是link,它说明了如何编写tryCatch。请注意,由于我未运行代码块,因此此代码段可能无法完全正常运行。但是,再次调用API调用程序时,应该可以完成该工作。

选中此link,以获取有关类似问题的讨论。

答案 1 :(得分:1)

这里是更新的脚本,其中直接在函数中包含TryCatch

indexed_url <- function(url){

  url_to_check <- as.character(url)

  api_request <- paste("https://script.google.com/macros/blablabalbalbaexec",
                       "?page=",url_to_check,sep="")
  api_request <- URLencode(api_request, repeated = TRUE)  
  source <- tryCatch({
    fromJSON(file = api_request)#Convertir un Json file en Data Frame  
  }, error = function(e) {
    cat(paste0("Une erreur a eu lieu :",e))
    Sys.sleep(1)
    indexed_url(url)
  })  
  return(data.frame(do.call("rbind", source)))
}

然后以运行良好的方式运行foreach。没有更多的错误,我得到了完整的分析。