【问题标题】:Store errors and warnings with tryCatch() in a list使用 tryCatch() 将错误和警告存储在列表中
【发布时间】:2021-10-25 22:05:03
【问题描述】:

我编写了一段代码,用于从 API 中提取 JSON 数据并将其转换为数据框。基本代码是:

hospitals_url <- "https://services1.arcgis.com/Hp6G80Pky0om7QvQ/arcgis/rest/services/Hospitals_1/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json"
        hospitals_num <- c(0, 2000, 4000, 6000)
        hosget <- lapply(hospitals_num, function(num) {
          hospitals_url_loop <- paste(hospitals_url, "&resultOffset=", num)
          hospitals_json <- fromJSON(hospitals_url_loop)
          hospitals_df <- as.data.frame(hospitals_json$features$attributes)})
        
        hospitals_df <- do.call(rbind, hosget)}

我正在尝试将其添加到 tryCatch() 函数中,以便我可以更多地参与错误管理和控制。我要做的是使用tryCatch() 函数的错误和警告部分来创建包含错误(如果有的话)的变量,并将它们放入列表中。我有以下内容:

tryCatch({
        hospitals_url <- "https://services1.arcgis.com/Hp6G80Pky0om7QvQ/arcgis/rest/services/Hospitals_1/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json"
        hospitals_num <- c(0, 2000, 4000, 6000)
        hosget <- lapply(hospitals_num, function(num) {
          hospitals_url_loop <- paste(hospitals_url, "&resultOffset=", num)
          hospitals_json <- fromJSON(hospitals_url_loop)
          hospitals_df <- as.data.frame(hospitals_json$features$attributes)})
        
        hospitals_df <- do.call(rbind, hosget)},
      
      error = function(hosp_e){
              hosp_e <- simpleError("Error: Hospital data has not been collected due to an error. Please ensure that the number loop is correct.")
              print(hosp_e)},
      
      warning = function(hosp_w){
              hosp_w <- simpleWarning("Warning: Hospital data has not been collected. Please ensure that the number loop is correct.")
              print(hosp_w)},
        
      finally = {
              hospitals_log <- (paste("Hospitals Code Has Been Executed on ", Sys.Date()))
              hosp_error <- if (exists("hosp_e") == FALSE) {
                      ("No Error")}
              hosp_warning <- if (exists("hosp_w") == FALSE) {
                      ("No Warning")}
              print(paste(hospitals_log, ", ", hosp_error, ", ", hosp_warning))
              hospitals_output = list(hospitals_log, hosp_error, hosp_warning, paste("URL: ", hospitals_url))
              rm(hospitals_log, hosp_warning, hosp_error, hospitals_num, hosget, hospitals_url)
                })

当我创建一个错误(例如,向 hospital_url 添加一个额外的“l”)时,我的 simpleerror 会打印出 (&lt;simpleError: Error: Hospital data has not been collected due to an error. Please ensure that the number loop is correct.&gt;),但不会存储为变量并添加到列表中。如何更改我的代码来完成此操作?

我查看了以下内容(herehere),但现在更加困惑... :(

【问题讨论】:

  • 由于您的tryCatch 包含整个过程,因此任何步骤中的任何错误或警告都会中断该过程并且不会重新进入它。我认为您需要 tryCatch 将代码包含在您的 lapply anonfunc 中。
  • @r2evans,你能举例说明你的意思吗?如果我提供有关我预期结果的背景信息,这可能会很有用。我正在寻找数据框,以及包含指定错误/无错误和警告/无警告消息的列表,用于记录目的。
  • 除了@r2evans 发现的另一个问题是hosp_ehosp_w 是错误和警告函数中的局部变量。如果你想保存一些东西,你需要在这些函数之外创建一个地方来保存它,并让这些函数在那里存储一些东西。
  • @user2554330 您能否通过示例或指向另一个 SO 问题/答案的链接进一步解释一下?

标签: r error-handling try-catch


【解决方案1】:

这是一个将tryCatch 放入循环中并保存生成的错误和警告的版本:

  hospitals_url <- "https://services1.arcgis.com/Hp6G80Pky0om7QvQ/arcgis/rest/services/Hospitals_1/FeatureServer/0/query?where=1%3D1&outFields=*&outSR=4326&f=json"
  hospitals_num <- c(0, 2000, 4000, 6000)
  hosp_e <- list()
  hosp_w <- list()
  
  hosget <- lapply(hospitals_num, function(num) {
    tryCatch({
      hospitals_url_loop <- paste(hospitals_url, "&resultOffset=", num)
      hospitals_json <- fromJSON(hospitals_url_loop)
      hospitals_df <- as.data.frame(hospitals_json$features$attributes)},
      error = function(e){
        hosp_e <<- c(hosp_e, list(e))
        print(e)},
      
      warning = function(w){
        hosp_w <<- c(hosp_w, list(w))
        print(w)}     
      ) })
    
  hospitals_df <- do.call(rbind, hosget)
  

我没有使您的finally 代码适应这种重新排列;我会把它留给你。但最后,hosp_e 将是一个包含所有错误的列表,hosp_w 将是一个包含所有警告的列表。

【讨论】:

  • 这正是我想要的,谢谢。我没有意识到我必须事先初始化错误和警告列表。我很感激!
  • 另一种方法是在error=/warning= 块中替换return(e)(和w),然后是事后hosp_e &lt;- Filter(function(z) inherits(z, "error"), hosget)(然后是inherits(z, "warning"))。这样,您不必&lt;&lt;- 超出范围。然后使用Filter(function(z) !inherits(z, c("error", "warning")), hosget) 获取“真实”数据。
  • @r2evans:这是个好主意。不过,这可能会导致警告出现问题:您会失去真正的答案,不是吗?
  • 我认为您已经通过tryCatch发出警告而失去了答案。我相信您需要使用muffleWarning(而不是)来捕获警告并继续处理。
猜你喜欢
  • 1970-01-01
  • 2017-02-25
  • 2019-12-31
  • 2013-10-26
  • 2013-02-24
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 2020-03-16
相关资源
最近更新 更多