You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在R脚本出错时暂停?API报错时用sys.sleep及tryCatch的疑问

回答:是的,tryCatch 是实现这个需求的理想方案

完全可以用 tryCatch 来捕获API请求抛出的错误(比如你遇到的HTTP 429速率限制错误),并在捕获到错误时执行 sys.sleep() 暂停脚本,甚至可以加上重试逻辑让脚本自动重新尝试请求。

基础实现示例

先给你一个最基础的版本,捕获429错误后暂停一段时间并重新请求:

library(jsonlite)

# 封装API请求逻辑
fetch_api_data <- function(api_url) {
  tryCatch(
    expr = {
      # 尝试发起API请求
      data <- fromJSON(api_url)
      return(data)
    },
    error = function(e) {
      # 判断是否是目标429错误
      if (grepl("HTTP error 429", e$message)) {
        message("触发API速率限制,暂停10秒后重试...")
        Sys.sleep(10)
        # 递归调用函数重新发起请求
        return(fetch_api_data(api_url))
      } else {
        # 其他类型错误直接抛出,不处理
        stop(e)
      }
    }
  )
}

# 调用函数获取数据
data <- fetch_api_data("https://api.com")

进阶优化:限制重试次数 + 动态等待时间

上面的递归可能会无限重试,建议加上重试次数限制;另外很多API返回429错误时,会在响应头里携带 Retry-After 字段,明确告知需要等待的秒数,我们可以利用这个字段来动态设置暂停时间:

library(jsonlite)
library(httr) # 用于获取响应头信息

fetch_api_data <- function(api_url, max_retries = 3) {
  for (retry_count in 1:max_retries) {
    tryCatch(
      expr = {
        # 用httr发送请求,方便获取响应头
        response <- GET(api_url)
        stop_for_status(response) # 主动触发HTTP错误
        data <- fromJSON(content(response, "text"))
        return(data)
      },
      error = function(e) {
        if (grepl("HTTP error 429", e$message) && retry_count < max_retries) {
          # 提取Retry-After值,没有则默认等待10秒
          wait_time <- as.integer(headers(response)$`retry-after`) %||% 10
          message(sprintf("第%d次触发速率限制,等待%d秒后重试...", retry_count, wait_time))
          Sys.sleep(wait_time)
        } else {
          stop(sprintf("API请求失败,已尝试%d次:%s", retry_count, e$message))
        }
      }
    )
  }
}

# 调用函数获取数据
data <- fetch_api_data("https://api.com")

核心逻辑说明

  • tryCatcherror参数可以精准捕获fromJSONstop_for_status抛出的异常,让你能自定义错误处理流程。
  • HTTP 429错误是典型的速率限制提示,暂停后重试是最贴合场景的解决方案。
  • 加上重试次数限制,可以避免脚本因持续触发错误而无限循环。

内容的提问来源于stack exchange,提问作者ML_Enthousiast

火山引擎 最新活动