R Academy · 课时

使用 tryCatch() 恢复错误

使用 tryCatch() 捕获并处理错误、警告和消息

第 2 / 4 课13 个步骤

使用 tryCatch() 恢复错误 是 CoddyKit 上的免费 R Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

什么是 tryCatch()?

tryCatch() 允许您运行一个表达式,并拦截它发出的任何条件(错误、警告或消息)。如果表达式成功,其值会被返回。如果表达式发出条件,则会改为调用匹配的处理程序。

result <- tryCatch({
  sqrt(16)
}, error = function(e) {
  NA
})
cat('Result:', result, '\n')

捕获错误

当 tryCatch() 内部的表达式调用 stop() 时,执行会跳转到 error 处理程序。处理程序会接收条件对象,并将其返回值作为整个 tryCatch() 调用的结果。

safe_divide <- function(x, y) {
  tryCatch({
    if (y == 0) stop('division by zero')
    x / y
  }, error = function(e) {
    cat('Caught error:', conditionMessage(e), '\n')
    NA
  })
}
cat(safe_divide(10, 2), '\n')
cat(safe_divide(10, 0), '\n')

捕获警告

warning 处理程序的工作方式与 error 处理程序相同,但它拦截的是警告条件。请注意:一旦在 tryCatch() 中定义了 warning 处理程序,警告就会像错误一样导致非局部退出,执行不会在警告之后继续。

result <- tryCatch({
  log(-1)
}, warning = function(w) {
  cat('Warning caught:', conditionMessage(w), '\n')
  -999
})
cat('Result:', result, '\n')

捕获消息

您还可以捕获 message() 条件。这样,您就能拦截并重新格式化不受您控制的函数所产生的信息性输出。处理程序会接收条件对象,而消息文本末尾包含一个换行符。

result <- tryCatch({
  message('Loading data...')
  42
}, message = function(m) {
  cat('Intercepted message:', trimws(conditionMessage(m)), '\n')
  -1
})
cat('Result:', result, '\n')

finally 子句

finally 块总是在表达式执行后运行——无论表达式成功、出错还是发出警告。您可以使用它执行清理代码,例如关闭连接、重置选项或记录完成情况。

result <- tryCatch({
  cat('Trying...\n')
  stop('oops')
}, error = function(e) {
  cat('Handled:', e$message, '\n')
  -1
}, finally = {
  cat('Finally block always runs\n')
})
cat('Result:', result, '\n')

多个处理程序

您可以在一次 tryCatch() 调用中为多种条件类型提供处理程序。R 会匹配第一个适用的处理程序。如果同时定义了 error 和 warning 处理程序,警告会在变成错误之前被捕获。

handle_it <- function(expr_result) {
  tryCatch(expr_result,
    error   = function(e) paste('ERROR:', e$message),
    warning = function(w) paste('WARN:', w$message),
    message = function(m) paste('MSG:', trimws(m$message))
  )
}
cat(handle_it(stop('bad input')), '\n')
cat(handle_it(log(-1)), '\n')

循环中的错误恢复

一种非常实用的模式是:将循环体包装在 tryCatch() 中,这样某次迭代失败就不会停止整个循环。当您处理可能以不可预测方式失败的文件、应用程序接口调用或用户输入时,这一点至关重要。

inputs <- list(4, -1, 0, 16, 'x')
results <- vector('list', length(inputs))
for (i in seq_along(inputs)) {
  results[[i]] <- tryCatch(
    sqrt(as.numeric(inputs[[i]])),
    warning = function(w) NA,
    error   = function(e) NA
  )
}
cat('Results:', unlist(results), '\n')

出错时返回有意义的默认值

一种简洁的模式是让错误处理程序返回一个合理的默认值。处理程序的返回值会成为 tryCatch() 的结果。返回 NA、NULL、0 或默认列表都很合适。

safe_parse <- function(x) {
  tryCatch(
    as.numeric(x),
    warning = function(w) {
      cat('Cannot parse:', x, '-> using 0\n')
      0
    }
  )
}
cat(safe_parse('3.14'), '\n')
cat(safe_parse('abc'), '\n')
cat(safe_parse('99'), '\n')

提取错误消息

在错误处理程序中,使用 conditionMessage(e) 或简写形式 e$message 获取错误文本。使用 conditionCall(e) 或 e$call 获取触发该错误的调用。

tryCatch(
  stop('file not found: data.csv'),
  error = function(e) {
    cat('Message:', conditionMessage(e), '\n')
    cat('Class  :', paste(class(e), collapse=', '), '\n')
  }
)

tryCatch() 与 try()

R 还提供了更简单的 try(expr) 函数。发生错误时,它会返回一个 'try-error' 类对象,而不是停止执行。需要快速完成一行操作时使用 try();需要完全控制处理程序或需要 finally 块时使用 tryCatch()。

# try() returns try-error object on failure
result <- try(log('x'), silent = TRUE)
if (inherits(result, 'try-error')) {
  cat('try() caught error\n')
} else {
  cat('Result:', result, '\n')
}

嵌套 tryCatch() 调用

tryCatch() 调用可以嵌套。内部的 tryCatch() 会先捕获条件;如果它重新抛出条件(使用 stop(e)),外部处理程序就会捕获重新抛出的条件。

outer_result <- tryCatch({
  tryCatch({
    stop('inner error')
  }, error = function(e) {
    cat('Inner handler, re-throwing\n')
    stop(paste('Wrapped:', e$message))
  })
}, error = function(e) {
  cat('Outer handler:', e$message, '\n')
  'recovered'
})
cat('Final:', outer_result, '\n')

快速检查

在 tryCatch() 中,无论是否发生错误,哪个子句都会始终运行?

tryCatch():要点总结

tryCatch() 的要点:

  • 使用 error = function(e) {...} 拦截错误,使用 warning = function(w) {...} 拦截警告
  • 处理程序的返回值会成为 tryCatch() 的结果
  • finally 始终执行,非常适合进行清理
  • 将循环体包装在 tryCatch() 中,以便对不可靠的输入进行稳健迭代
  • e$message 或 conditionMessage(e) 可提取错误文本
  • try(expr, silent=TRUE) 是更简单的单行替代方案
safe_op <- function(x) {
  tryCatch({
    if (!is.numeric(x)) stop('not numeric')
    sqrt(x)
  }, error = function(e) {
    cat('Error:', e$message, '\n')
    NA
  }, finally = {
    cat('Done processing', x, '\n')
  })
}
cat(safe_op(9), '\n')
cat(safe_op('a'), '\n')
免费开始

用 AI 导师学习 R — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
43
课程
159

常见问题解答

「使用 tryCatch() 恢复错误」课时是免费的吗?

是的 — 「使用 tryCatch() 恢复错误」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「使用 tryCatch() 恢复错误」这节课中我会学到什么?

使用 tryCatch() 捕获并处理错误、警告和消息 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「使用 tryCatch() 恢复错误」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. R 中的错误、警告与消息
  2. 使用 tryCatch() 恢复错误
  3. withCallingHandlers() 与重启机制
  4. 使用 stop() 和 warning() 编写稳健函数
← 返回 R Academy