如何停止R中花费太长时间的函数并为其提供替代方案?

如何停止R中花费太长时间的函数并为其提供替代方案?,r,time,error-handling,R,Time,Error Handling,我想用“正确的方式”做一件事。有时,“正确的方法”需要太长时间,这取决于输入。我真的不知道什么时候会这样。当“正确的方式”花费的时间太长时,我想选择“黑客方式”。我如何让R监视一个特定任务所花费的时间,并在超过阈值时给它一些其他的事情去做?我想这将是try家族的一部分,但我不太确定该如何称呼它或谷歌 下面是一个虚拟示例。当slow.func花费的时间太长时,我希望interuptor停止它并调用fast.func slow.func <- function(x){ Sys.slee

我想用“正确的方式”做一件事。有时,“正确的方法”需要太长时间,这取决于输入。我真的不知道什么时候会这样。当“正确的方式”花费的时间太长时,我想选择“黑客方式”。我如何让R监视一个特定任务所花费的时间,并在超过阈值时给它一些其他的事情去做?我想这将是
try
家族的一部分,但我不太确定该如何称呼它或谷歌

下面是一个虚拟示例。当
slow.func
花费的时间太长时,我希望
interuptor
停止它并调用
fast.func

slow.func <- function(x){
    Sys.sleep(x)    
    print('good morning')
}

fast.func <- function(x){
    Sys.sleep(x/10) 
    print('hit snooze')
}

interuptor = function(FUN,args, time.limit, ALTFUN){
#   START MONITORING TIME HERE
    do.call(FUN,args)
#   IF FUN TAKES TOO LONG, STOP IT, CALL A
    do.call(ALTFUN,args)
}

interuptor(slow.func, list(x = 2), time.limit = 1, fast.func)

slow.funcR包
R.utils
有一个函数
evalWithTimeout
,这正是您所描述的。如果您不想安装软件包,
evalWithTimeout
依赖于用户不太友好的R base函数
setTimeLimit

您的代码如下所示:

library(R.utils)

slow.func <- function(x){
  Sys.sleep(10)    
  return(x^2)
}

fast.func <- function(x){
  Sys.sleep(2) 
return(x*x)
}
interruptor = function(FUN,args, time.limit, ALTFUN){
  results <- NULL
  results <- evalWithTimeout({FUN(args)},timeout=time.limit,onTimeout="warning")
  if(results==NULL){
    results <- ALTFUN(args)
  }
  return(results)
}   
interruptor(slow.func,args=2,time.limit=3,fast.func)
库(R.utils)

slow.func我发布的初始版本使用了“R.utils v2.5.0(2016-11-07)”,但没有使用“R.utils v2.9.2”。下面是使用“R.utils v2.9.2”进行了一些修改的版本

带有“R.utils v2.5.0”的版本 “nwknoblauch”的答案对我不起作用,除非我在中断器函数中通过“静默”更改“警告”

library(R.utils)

slow.func <- function(x){
  Sys.sleep(10)    
  return(x^2)
}

fast.func <- function(x){
  Sys.sleep(2) 
return(x*x)
}

interruptor = function(FUN,args, time.limit, ALTFUN){
  results <- NULL
  results <- evalWithTimeout({FUN(args)},timeout=time.limit,onTimeout="silent")
  if(is.null(results)){
    results <- ALTFUN(args)
  }
  return(results)
}   

interruptor(FUN = slow.func,args=2,time.limit=3,ALTFUN = fast.func)
库(R.utils)

slow.func对于任何想要不依赖于
R.utils
包的更轻量级解决方案的人,我最终使用了基于
withTimeout()
代码的最小解决方案

foo <- function() {

  time_limit <- 10

  setTimeLimit(cpu = time_limit, elapsed = time_limit, transient = TRUE)
  on.exit({
    setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
  })

  tryCatch({
    # do some stuff
  }, error = function(e) {
    if (grepl("reached elapsed time limit|reached CPU time limit", e$message)) {
      # we reached timeout, apply some alternative method or do something else
    } else {
      # error not related to timeout
      stop(e)
    }
  })

}

foo如何添加时间检查?是的,我只是在运行R。我还没有学过任何C。在这种情况下,编写和编译一个简单的C程序并用
.C
调用它会很简单吗?不起作用:
错误:“evalWithTimeout”已失效。改为使用“R.utils::withTimeout()”。请参阅帮助(“已失效”)
时间流逝和版本更改。我修改了这个函数,它似乎又能工作了。我目前正在使用R版本3.6.0和R.utils v2.9.2
test_obj <- interruptor(FUN = slow.func, args=5, time.limit= 6, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args=5, time.limit= 3, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args="A", time.limit= 6, ALTFUN = fast.func)
test_obj
test_obj <- interruptor(FUN = slow.func, args="A", time.limit= 3, ALTFUN = fast.func)
test_obj
foo <- function() {

  time_limit <- 10

  setTimeLimit(cpu = time_limit, elapsed = time_limit, transient = TRUE)
  on.exit({
    setTimeLimit(cpu = Inf, elapsed = Inf, transient = FALSE)
  })

  tryCatch({
    # do some stuff
  }, error = function(e) {
    if (grepl("reached elapsed time limit|reached CPU time limit", e$message)) {
      # we reached timeout, apply some alternative method or do something else
    } else {
      # error not related to timeout
      stop(e)
    }
  })

}