在R中,我遍历对象向量,并在每次迭代时应用相同的命令。如何(i)停止耗时太长的迭代,(ii)打印错误/警告消息,(iii)进行下一个迭代?
例如,假设我有一个包含3个时间段的向量,并且我将这5个时间段限制为R个睡眠时间。 如果for循环迭代花费的时间超过5秒(此处为向量的第二个),则应在5秒左右停止并继续运行。
以下代码的问题是,如果迭代花费的时间太长,R不会停止,而是仅在迭代完成后才打印错误消息,而不是在时限内直接输出。
vec <- c(2, 12, 3)
# using base R 'setTimeLimit' function
for(i in 1:length(vec)){
cat(". Sleeping", vec[i], "seconds\n")
tryCatch(
{
system.time(
local(
{
setTimeLimit(elapsed = 5, transient = TRUE)
Sys.sleep(vec[i])
}
)
)
},
error=function(e){cat(conditionMessage(e), "\n")}
)
}
# using R.utils 'withTimeout' function
library(R.utils)
for(i in 1:length(vec)){
cat(". Sleeping", vec[i], "seconds\n")
# first 'tryCatch' if error NOT caused by a timeout
tryCatch(
# second 'tryCatch' if error caused by a timeout
tryCatch(
withTimeout(
Sys.sleep(vec[i]),
timeout=5,
onTimeout="error"
),
TimeoutException = function(ex) cat("Timeout. Skipping.\n")
),
error=function(e){cat(conditionMessage(e), "\n")}
)
}
编辑
如评论中所述,此solution不适用于我的示例。
for(i in 1:length(vec)){
+ tryCatch(
+ expr = {
+ withTimeout({Sys.sleep(vec[i]); cat(". Sleeping ", vec[i], " seconds\n")},
+ timeout = 5)
+ },
+ TimeoutException = function(ex) cat("Timeout. Skipping.\n")
+ )
+ }
它输出:
. Sleeping 2 seconds
Timeout. Skipping. # this message shows up after 12 seconds anyway (I am trying to stop it after timeout = 5s here)
. Sleeping 3 seconds
编辑2
我的涉及Sys.sleep
函数的示例不适用于withTimeout
。
摘自R.Utils
手册:
(*)请注意,在Unix和macOS上,Sys.sleep(time)将发出超时通知 无论经过超时限制(< 时间)。
再举一个例子,下面的评论中提到的SO帖子实际上是有效的。
library(R.utils)
vec <- c(1e+02, 1e+06, 1e+04)
# the second element of the vector takes some time to run
foo <- function(i){
for(j in 1:i){
invisible(capture.output(print(j)))
}
}
# checking that the second element will take a long time (15 seconds)
system.time(foo(vec[1]))
# user system elapsed
# 0.002 0.001 0.001
system.time(foo(vec[2]))
# user system elapsed
# 11.557 3.157 15.543
system.time(foo(vec[3]))
# user system elapsed
# 0.109 0.031 0.148
for(k in vec){
tryCatch(
{
system.time(withTimeout(
{cat("... Processing ", k, " times...\n\n"); invisible(capture.output(foo(k)))},
timeout = 5
))
},
TimeoutException = function(ex) cat("Timeout. Skipping.\n\n")
)
}
#... Processing 100 times...
#
#... Processing 1e+06 times...
#
#Timing stopped at: 4.993 0.029 5.022 # it stops at timeout = 5s
#Timeout. Skipping.
#
#... Processing 10000 times...